Don't check UTF-8 correctness when inserting chars
- Fix bug when inserting char ranges that are not arrays - Optimize insertion from the String own range - Assume char and char ranges are correclty encoded (as it actually should be) and don't throw an exception. This should make the most common use cases nothrow (Fix #19). Dchars and Wchars are still encoded because they should be converted to UTF-8 before inserting anyway.
This commit is contained in:
parent
a332d727af
commit
3df4eb6259
@ -500,7 +500,7 @@ struct String
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@nogc pure @safe unittest
|
@nogc nothrow pure @safe unittest
|
||||||
{
|
{
|
||||||
auto s = String(0, 'K');
|
auto s = String(0, 'K');
|
||||||
assert(s.length == 0);
|
assert(s.length == 0);
|
||||||
@ -580,16 +580,10 @@ struct String
|
|||||||
* Params:
|
* Params:
|
||||||
* chr = The character should be inserted.
|
* chr = The character should be inserted.
|
||||||
*
|
*
|
||||||
* Returns: The number of bytes inserted.
|
* Returns: The number of bytes inserted (1).
|
||||||
*
|
|
||||||
* Throws: $(D_PSYMBOL UTFException).
|
|
||||||
*/
|
*/
|
||||||
size_t insertBack(const char chr) @nogc pure @trusted
|
size_t insertBack(char chr) @nogc nothrow pure @trusted
|
||||||
{
|
{
|
||||||
if ((chr & 0x80) != 0)
|
|
||||||
{
|
|
||||||
throw defaultAllocator.make!UTFException("Invalid UTF-8 character");
|
|
||||||
}
|
|
||||||
reserve(length + 1);
|
reserve(length + 1);
|
||||||
|
|
||||||
*(data + length) = chr;
|
*(data + length) = chr;
|
||||||
@ -653,8 +647,6 @@ struct String
|
|||||||
* str = String should be inserted.
|
* str = String should be inserted.
|
||||||
*
|
*
|
||||||
* Returns: The number of bytes inserted.
|
* Returns: The number of bytes inserted.
|
||||||
*
|
|
||||||
* Throws: $(D_PSYMBOL UTFException).
|
|
||||||
*/
|
*/
|
||||||
size_t insertBack(R)(R str) @trusted
|
size_t insertBack(R)(R str) @trusted
|
||||||
if (!isInfinite!R
|
if (!isInfinite!R
|
||||||
@ -674,46 +666,18 @@ struct String
|
|||||||
this.length_ = size;
|
this.length_ = size;
|
||||||
return str.length;
|
return str.length;
|
||||||
}
|
}
|
||||||
|
else static if (isInstanceOf!(ByCodeUnit, R))
|
||||||
|
{
|
||||||
|
str.get.copy(this.data[length .. size]);
|
||||||
|
this.length_ = size;
|
||||||
|
return str.length;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
size_t insertedLength;
|
size_t insertedLength;
|
||||||
while (!str.empty)
|
foreach (c; str)
|
||||||
{
|
{
|
||||||
ubyte expectedLength;
|
insertedLength += insertBack(c);
|
||||||
if ((str.front & 0x80) == 0x00)
|
|
||||||
{
|
|
||||||
expectedLength = 1;
|
|
||||||
}
|
|
||||||
else if ((str.front & 0xe0) == 0xc0)
|
|
||||||
{
|
|
||||||
expectedLength = 2;
|
|
||||||
}
|
|
||||||
else if ((str.front & 0xf0) == 0xe0)
|
|
||||||
{
|
|
||||||
expectedLength = 3;
|
|
||||||
}
|
|
||||||
else if ((str.front & 0xf8) == 0xf0)
|
|
||||||
{
|
|
||||||
expectedLength = 4;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
throw defaultAllocator.make!UTFException("Invalid UTF-8 sequeunce");
|
|
||||||
}
|
|
||||||
size = length + expectedLength;
|
|
||||||
reserve(size);
|
|
||||||
|
|
||||||
for (; expectedLength > 0; --expectedLength)
|
|
||||||
{
|
|
||||||
if (str.empty)
|
|
||||||
{
|
|
||||||
throw defaultAllocator.make!UTFException("Invalid UTF-8 sequeunce");
|
|
||||||
}
|
|
||||||
*(data + length) = str.front;
|
|
||||||
str.popFront();
|
|
||||||
}
|
|
||||||
insertedLength += expectedLength;
|
|
||||||
this.length_ = size;
|
|
||||||
}
|
}
|
||||||
return insertedLength;
|
return insertedLength;
|
||||||
}
|
}
|
||||||
@ -829,7 +793,7 @@ struct String
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
@nogc pure @safe unittest
|
@nogc nothrow pure @safe unittest
|
||||||
{
|
{
|
||||||
String s;
|
String s;
|
||||||
assert(s.capacity == 0);
|
assert(s.capacity == 0);
|
||||||
@ -870,7 +834,7 @@ struct String
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
@nogc pure @safe unittest
|
@nogc nothrow pure @safe unittest
|
||||||
{
|
{
|
||||||
auto s = String("Die Alten lasen laut.");
|
auto s = String("Die Alten lasen laut.");
|
||||||
assert(s.capacity == 21);
|
assert(s.capacity == 21);
|
||||||
@ -895,7 +859,7 @@ struct String
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
@nogc pure @safe unittest
|
@nogc nothrow pure @safe unittest
|
||||||
{
|
{
|
||||||
auto s = String("In allem Schreiben ist Schamlosigkeit.");
|
auto s = String("In allem Schreiben ist Schamlosigkeit.");
|
||||||
assert(s.capacity == 38);
|
assert(s.capacity == 38);
|
||||||
@ -992,7 +956,7 @@ struct String
|
|||||||
*
|
*
|
||||||
* Returns: Null-terminated string.
|
* Returns: Null-terminated string.
|
||||||
*/
|
*/
|
||||||
const(char)* toStringz() @nogc nothrow pure
|
const(char)* toStringz() @nogc nothrow pure @system
|
||||||
{
|
{
|
||||||
reserve(length + 1);
|
reserve(length + 1);
|
||||||
this.data[length] = '\0';
|
this.data[length] = '\0';
|
||||||
@ -1000,7 +964,7 @@ struct String
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
@nogc pure unittest
|
@nogc nothrow pure @system unittest
|
||||||
{
|
{
|
||||||
auto s = String("C string.");
|
auto s = String("C string.");
|
||||||
assert(s.toStringz()[0] == 'C');
|
assert(s.toStringz()[0] == 'C');
|
||||||
@ -1019,7 +983,7 @@ struct String
|
|||||||
alias opDollar = length;
|
alias opDollar = length;
|
||||||
|
|
||||||
///
|
///
|
||||||
@nogc pure @safe unittest
|
@nogc nothrow pure @safe unittest
|
||||||
{
|
{
|
||||||
auto s = String("Piscis primuin a capite foetat.");
|
auto s = String("Piscis primuin a capite foetat.");
|
||||||
assert(s.length == 31);
|
assert(s.length == 31);
|
||||||
@ -1045,7 +1009,7 @@ struct String
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
@nogc pure @safe unittest
|
@nogc nothrow pure @safe unittest
|
||||||
{
|
{
|
||||||
auto s = String("Alea iacta est.");
|
auto s = String("Alea iacta est.");
|
||||||
assert(s[0] == 'A');
|
assert(s[0] == 'A');
|
||||||
@ -1068,7 +1032,7 @@ struct String
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
@nogc pure @safe unittest
|
@nogc nothrow pure @safe unittest
|
||||||
{
|
{
|
||||||
auto s = String("Plutarchus");
|
auto s = String("Plutarchus");
|
||||||
auto r = s[];
|
auto r = s[];
|
||||||
@ -1087,7 +1051,7 @@ struct String
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
@nogc pure @safe unittest
|
@nogc nothrow pure @safe unittest
|
||||||
{
|
{
|
||||||
auto s = const String("Was ich vermag, soll gern geschehen. Goethe");
|
auto s = const String("Was ich vermag, soll gern geschehen. Goethe");
|
||||||
auto r1 = s[];
|
auto r1 = s[];
|
||||||
@ -1163,7 +1127,7 @@ struct String
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
@nogc pure @safe unittest
|
@nogc nothrow pure @safe unittest
|
||||||
{
|
{
|
||||||
String s;
|
String s;
|
||||||
assert(s.empty);
|
assert(s.empty);
|
||||||
@ -1208,7 +1172,7 @@ struct String
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
@nogc pure @safe unittest
|
@nogc nothrow pure @safe unittest
|
||||||
{
|
{
|
||||||
auto s = String("Vladimir Soloviev");
|
auto s = String("Vladimir Soloviev");
|
||||||
auto r = s[9 .. $];
|
auto r = s[9 .. $];
|
||||||
@ -1272,7 +1236,7 @@ struct String
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
@nogc pure @safe unittest
|
@nogc nothrow pure @safe unittest
|
||||||
{
|
{
|
||||||
auto s = String("Черная, потом пропахшая выть!");
|
auto s = String("Черная, потом пропахшая выть!");
|
||||||
s = String("Как мне тебя не ласкать, не любить?");
|
s = String("Как мне тебя не ласкать, не любить?");
|
||||||
@ -1300,10 +1264,11 @@ struct String
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
@nogc pure @safe unittest
|
@nogc nothrow pure @safe unittest
|
||||||
{
|
{
|
||||||
auto s = String("Оловом светится лужная голь...");
|
auto s = String("Оловом светится лужная голь...");
|
||||||
s = "Грустная песня, ты - русская боль.";
|
s = "Грустная песня, ты - русская боль.";
|
||||||
|
assert(s == "Грустная песня, ты - русская боль.");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1345,7 +1310,7 @@ struct String
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
@nogc pure @safe unittest
|
@nogc nothrow pure @safe unittest
|
||||||
{
|
{
|
||||||
assert(String("Голубая кофта.") < String("Синие глаза."));
|
assert(String("Голубая кофта.") < String("Синие глаза."));
|
||||||
assert(String("Никакой я правды") < String("милой не сказал")[]);
|
assert(String("Никакой я правды") < String("милой не сказал")[]);
|
||||||
@ -1398,7 +1363,7 @@ struct String
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
@nogc pure @safe unittest
|
@nogc nothrow pure @safe unittest
|
||||||
{
|
{
|
||||||
assert(String("Милая спросила:") != String("Крутит ли метель?"));
|
assert(String("Милая спросила:") != String("Крутит ли метель?"));
|
||||||
assert(String("Затопить бы печку,") != String("постелить постель.")[]);
|
assert(String("Затопить бы печку,") != String("постелить постель.")[]);
|
||||||
@ -1431,7 +1396,7 @@ struct String
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
@nogc pure @safe unittest
|
@nogc nothrow pure @safe unittest
|
||||||
{
|
{
|
||||||
auto s = String("alea iacta est.");
|
auto s = String("alea iacta est.");
|
||||||
|
|
||||||
@ -1456,7 +1421,7 @@ struct String
|
|||||||
return opSliceAssign(value, 0, length);
|
return opSliceAssign(value, 0, length);
|
||||||
}
|
}
|
||||||
|
|
||||||
@nogc pure @safe unittest
|
@nogc nothrow pure @safe unittest
|
||||||
{
|
{
|
||||||
auto s1 = String("Buttercup");
|
auto s1 = String("Buttercup");
|
||||||
auto s2 = String("Cap");
|
auto s2 = String("Cap");
|
||||||
@ -1470,7 +1435,7 @@ struct String
|
|||||||
return opSliceAssign(value, 0, length);
|
return opSliceAssign(value, 0, length);
|
||||||
}
|
}
|
||||||
|
|
||||||
@nogc pure @safe unittest
|
@nogc nothrow pure @safe unittest
|
||||||
{
|
{
|
||||||
auto s1 = String("Wow");
|
auto s1 = String("Wow");
|
||||||
s1[] = 'a';
|
s1[] = 'a';
|
||||||
@ -1483,7 +1448,7 @@ struct String
|
|||||||
return opSliceAssign(value, 0, length);
|
return opSliceAssign(value, 0, length);
|
||||||
}
|
}
|
||||||
|
|
||||||
@nogc pure @safe unittest
|
@nogc nothrow pure @safe unittest
|
||||||
{
|
{
|
||||||
auto s1 = String("ö");
|
auto s1 = String("ö");
|
||||||
s1[] = "oe";
|
s1[] = "oe";
|
||||||
@ -1575,7 +1540,7 @@ struct String
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
@nogc pure @safe unittest
|
@nogc nothrow pure @safe unittest
|
||||||
{
|
{
|
||||||
auto s = String("Казнить нельзя помиловать.");
|
auto s = String("Казнить нельзя помиловать.");
|
||||||
s.insertAfter(s[0 .. 27], ",");
|
s.insertAfter(s[0 .. 27], ",");
|
||||||
@ -1604,7 +1569,7 @@ struct String
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
@nogc pure @safe unittest
|
@nogc nothrow pure @safe unittest
|
||||||
{
|
{
|
||||||
auto s = String("Казнить нельзя помиловать.");
|
auto s = String("Казнить нельзя помиловать.");
|
||||||
s.insertBefore(s[27 .. $], ",");
|
s.insertBefore(s[27 .. $], ",");
|
||||||
@ -1628,8 +1593,8 @@ struct String
|
|||||||
mixin DefaultAllocator;
|
mixin DefaultAllocator;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Postblit works.
|
// Postblit works
|
||||||
@nogc pure @safe unittest
|
@nogc nothrow pure @safe unittest
|
||||||
{
|
{
|
||||||
void internFunc(String arg)
|
void internFunc(String arg)
|
||||||
{
|
{
|
||||||
@ -1648,7 +1613,7 @@ struct String
|
|||||||
topFunc(String("asdf"));
|
topFunc(String("asdf"));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Const range produces mutable ranges.
|
// Const range produces mutable ranges
|
||||||
@nogc pure @safe unittest
|
@nogc pure @safe unittest
|
||||||
{
|
{
|
||||||
auto s = const String("И снизу лед, и сверху - маюсь между.");
|
auto s = const String("И снизу лед, и сверху - маюсь между.");
|
||||||
@ -1674,7 +1639,7 @@ struct String
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Can pop multibyte characters.
|
// Can pop multibyte characters
|
||||||
@nogc pure @safe unittest
|
@nogc pure @safe unittest
|
||||||
{
|
{
|
||||||
auto s = String("\U00024B62\U00002260");
|
auto s = String("\U00024B62\U00002260");
|
||||||
@ -1691,3 +1656,12 @@ struct String
|
|||||||
s[$ - 3] = 0xf0;
|
s[$ - 3] = 0xf0;
|
||||||
assertThrown!UTFException(&(range.popFront));
|
assertThrown!UTFException(&(range.popFront));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Inserts own char range correctly
|
||||||
|
@nogc nothrow pure @safe unittest
|
||||||
|
{
|
||||||
|
auto s1 = String(`ü`);
|
||||||
|
String s2;
|
||||||
|
s2.insertBack(s1[]);
|
||||||
|
assert(s1 == s2);
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user