Bug 9456 – decodeFront is inconsistent in whether it pops elements off of the range or not
Status
RESOLVED
Resolution
FIXED
Severity
normal
Priority
P2
Component
phobos
Product
D
Version
D2
Platform
All
OS
All
Creation time
2013-02-05T17:05:00Z
Last change time
2013-05-17T13:34:51Z
Assigned to
issues.dlang
Creator
issues.dlang
Comments
Comment #0 by issues.dlang — 2013-02-05T17:05:12Z
This code
import std.array;
import std.conv;
import std.utf;
class RefRange(C)
{
@property bool empty() { return _str.empty; }
@property C front() { return _str[0]; }
void popFront() { _str = _str[1 .. $]; }
@property C back() { return _str[$ - 1]; }
void popBack() { _str = _str[0 .. $ - 1]; }
@property auto save() { return new RefRange(_str); }
@property size_t length() { return _str.length; }
this(inout(C)[] str)
{
_str = to!(C[])(str);
}
C[] _str;
}
void main()
{
auto asciiStr = "hello world";
auto asciiRange = new RefRange!char(asciiStr);
//auto asii = asciiStr;
size_t index = 1;
assert(asciiRange.decodeFront(index) == 'h');
assert(asciiRange.length == asciiStr.length);
auto uniStr = "プログラミング";
auto uniRange = new RefRange!char(uniStr);
//auto uniRange = uniStr;
index = 3;
assert(uniRange.decodeFront(index) == 'プ');
assert(uniRange.length == uniStr.length);
}
gives this error when it runs
core.exception.AssertError@q(37): Assertion failure
----------------
./q(_d_assertm+0x26) [0x42c946]
./q() [0x42ac22]
./q(_Dmain+0xfa) [0x42a3da]
./q(extern (C) int rt.dmain2._d_run_main(int, char**, extern (C) int function(char[][])*).void runMain()+0x18) [0x42d0dc]
./q(extern (C) int rt.dmain2._d_run_main(int, char**, extern (C) int function(char[][])*).void tryExec(scope void delegate())+0x2a) [0x42cc1a]
./q(extern (C) int rt.dmain2._d_run_main(int, char**, extern (C) int function(char[][])*).void runAll()+0x3b) [0x42d123]
./q(extern (C) int rt.dmain2._d_run_main(int, char**, extern (C) int function(char[][])*).void tryExec(scope void delegate())+0x2a) [0x42cc1a]
./q(_d_run_main+0x1a8) [0x42cbd4]
./q(main+0x17) [0x42ca27]
/usr/lib/libc.so.6(__libc_start_main+0xf5) [0x7f60c980aa15]
----------------
The last assertion fails. If you swap which lines are commented out so that strings are used instead of RefRange, then the code succeeds. The problem is that decodeFront calls popFront when dealing with unicode, and it doesn't save, so depending on what's passed to it, it may or may not pop elements. It's more efficient to save internally in the cases where it needs to rather than ask the caller to do so, so the correct fix is to make it save if it's going to pop anything.
I think this should be the other way around. decodeFront should ALWAYS alter its input.
This is the only way to make it work with input ranges.
Comment #3 by issues.dlang — 2013-02-10T03:47:54Z
New pull request: https://github.com/D-Programming-Language/phobos/pull/1129
It makes it so that decodeFront takes its argument by ref, since that's the only way to make it consistent across range types, much as it would ideally act like decode and never pop off any elements.
Comment #4 by github-bugzilla — 2013-04-27T23:10:35Z