diff --git a/src/jes/core/lineendings.d b/src/jes/core/lineendings.d new file mode 100644 index 0000000..d02938c --- /dev/null +++ b/src/jes/core/lineendings.d @@ -0,0 +1,61 @@ +module jes.core.lineendings; + +struct LineEndings +{ + enum : ubyte + { + LF, + CRLF, + } + + ubyte type; + alias type this; + + this(ubyte type) + { + this.type = type; + } + + static LineEndings detect_line_endings(const ubyte * data, size_t n) + { + size_t lf_count = 0u; + for (size_t i = 0u; i < n; i++) + { + if (data[i] == '\n') + { + lf_count++; + /* Every LF must be preceded by a CR for the content to have + * CRLF line endings. */ + if ((i == 0u) || (data[i - 1u] != '\r')) + { + return LineEndings(LF); + } + } + } + if (lf_count > 0u) + { + return LineEndings(CRLF); + } + return LineEndings(LF); + } + + unittest + { + import std.stdio; + import std.file; + const(ubyte)[] dat; + LineEndings le; + + dat = cast(const(ubyte)[])std.file.read("test/files/line_endings/crlf_format.txt"); + le = LineEndings.detect_line_endings(dat.ptr, dat.length); + assert(le == LineEndings.CRLF); + + dat = cast(const(ubyte)[])std.file.read("test/files/empty.txt"); + le = LineEndings.detect_line_endings(dat.ptr, 0u); + assert(le == LineEndings.LF); + + dat = cast(const(ubyte)[])std.file.read("test/files/line_endings/lf_format.txt"); + le = LineEndings.detect_line_endings(dat.ptr, dat.length); + assert(le == LineEndings.LF); + } +} diff --git a/test/files/line_endings/cr_format.txt b/test/files/line_endings/cr_format.txt deleted file mode 100644 index 2810e5c..0000000 --- a/test/files/line_endings/cr_format.txt +++ /dev/null @@ -1 +0,0 @@ -Hello. This file is in CR line ending format. \ No newline at end of file