vibe.d beta banner
get vibe.d

Asynchronous I/O that doesn’t get in your way, written in D

Function readUntil

Reads all data of a stream until the specified end marker is detected.

ubyte[] readUntil(InputStream, Allocator) (
  InputStream stream,
  in ubyte[] end_marker,
  size_t max_bytes = size_t.max,
  Allocator alloc = vibeThreadAllocator()
if (isInputStream!InputStream);

void readUntil(InputStream, OutputStream) (
  InputStream stream,
  OutputStream dst,
  in ubyte[] end_marker,
  ulong max_bytes = (ulong).max
if (isInputStream!InputStream && isOutputStream!OutputStream);

void readUntil(R, InputStream) (
  InputStream stream,
  ref R dst,
  in ubyte[] end_marker,
  ulong max_bytes = (ulong).max
if (isOutputRange!(R, ubyte) && isInputStream!InputStream);


stream The input stream which is searched for end_marker
end_marker The byte sequence which is searched in the stream
max_bytes An optional limit of how much data is to be read from the input stream; if the limit is reaached before hitting the end marker, an exception is thrown.
alloc An optional allocator that is used to build the result string in the string variant of this function
dst The output stream, to which the prefix to the end marker of the input stream is written


The string variant of this function returns the complete prefix to the end marker of the input stream, excluding the end marker itself.


An exception if either the stream end was hit without hitting a marker first, or if more than max_bytes have been read from the stream in case of max_bytes != 0.


This function uses an algorithm inspired by the Boyer-Moore string search algorithm. However, contrary to the original algorithm, it will scan the whole input string exactly once, without jumping over portions of it. This allows the algorithm to work with constant memory requirements and without the memory copies that would be necessary for streams that do not hold their complete data in memory.

The current implementation has a run time complexity of O(n*m+m²) and O(n+m) in typical cases, with n being the length of the scanned input string and m the length of the marker.


Sönke Ludwig


© 2012-2016 Sönke Ludwig


Subject to the terms of the MIT license, as written in the included LICENSE.txt file.