Skip to content

Instantly share code, notes, and snippets.

@sinfu
Created July 13, 2010 21:26
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sinfu/474562 to your computer and use it in GitHub Desktop.
Save sinfu/474562 to your computer and use it in GitHub Desktop.
import std.algorithm;
import std.exception;
import std.stdio;
import core.stdc.errno;
import core.stdc.stdlib;
void main()
{
auto r = LockingByteReader(stdin);
// for (ubyte c; r.getNext(c); )
for (ubyte* p; (p = getNext!ubyte(r)) != null; )
{
writeln(cast(dchar) *p);
}
}
E* getNext(E, R)(ref R input, ref E store = *(cast(E*) alloca(E.sizeof)))
{
static if (is(typeof(input.getNext(store)) == E*))
{
return input.getNext(store);
}
else
{
if (input.empty)
return null;
static if (is(typeof(&(0, input.front)) == E*))
{
auto p = &(0, input.front);
input.popFront;
return p;
}
else
{
store = input.front;
input.popFront;
return &store;
}
}
}
struct LockingByteReader
{
private File _file;
@trusted this(File file)
{
enforce(file.isOpen);
swap(_file, file);
FLOCK(_file.getFP());
}
@trusted this(this)
{
FLOCK(_file.getFP());
}
@trusted ~this()
{
FUNLOCK(_file.getFP());
}
@trusted ubyte* getNext(ref ubyte store)
{
auto handle = assumeUnshared(_file.getFP());
int c;
while ((c = FGETC(handle)) == EOF)
{
if (feof(cast(shared) handle))
return null;
switch (errno)
{
case EINTR:
continue;
default:
throw new StdioException(null);
}
}
store = cast(ubyte) c;
return &store;
}
@trusted void unget(ubyte c)
{
if (ungetc(c, _file.getFP()) == EOF)
throw new StdioException(null);
}
}
T* assumeUnshared(T)(shared(T)* p)
{
return cast(T*) p;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment