1 /******************************************************************************* 2 3 Copyright: 4 Copyright (c) 2004 Kris Bell. 5 Some parts copyright (c) 2009-2016 dunnhumby Germany GmbH. 6 All rights reserved. 7 8 License: 9 Tango Dual License: 3-Clause BSD License / Academic Free License v3.0. 10 See LICENSE_TANGO.txt for details. 11 12 Version: Initial release: January 2006 13 14 Authors: Kris 15 16 *******************************************************************************/ 17 18 module ocean.io.stream.Lines; 19 20 import ocean.meta.types.Qualifiers; 21 22 import ocean.io.stream.Iterator; 23 24 /******************************************************************************* 25 26 Iterate across a set of text patterns. 27 28 Each pattern is exposed to the client as a slice of the original 29 content, where the slice is transient. If you need to retain the 30 exposed content, then you should .dup it appropriately. 31 32 The content exposed via an iterator is supposed to be entirely 33 read-only. All current iterators abide by this rule, but it is 34 possible a user could mutate the content through a get() slice. 35 To enforce the desired read-only aspect, the code would have to 36 introduce redundant copying or the compiler would have to support 37 read-only arrays. 38 39 See Delimiters, Patterns, Quotes. 40 41 *******************************************************************************/ 42 43 class Lines : Iterator 44 { 45 /*********************************************************************** 46 47 Construct an uninitialized iterator. For example: 48 --- 49 auto lines = new Lines!(char); 50 51 void somefunc (InputStream stream) 52 { 53 foreach (line; lines.set(stream)) 54 Cout (line).newline; 55 } 56 --- 57 58 Construct a streaming iterator upon a stream: 59 --- 60 void somefunc (InputStream stream) 61 { 62 foreach (line; new Lines!(char) (stream)) 63 Cout (line).newline; 64 } 65 --- 66 67 Construct a streaming iterator upon a conduit: 68 --- 69 foreach (line; new Lines!(char) (new File ("myfile"))) 70 Cout (line).newline; 71 --- 72 73 ***********************************************************************/ 74 75 this (InputStream stream = null) 76 { 77 super (stream); 78 } 79 80 /*********************************************************************** 81 82 Read a line of text, and return false when there's no 83 further content available. 84 85 ***********************************************************************/ 86 87 final bool readln (ref cstring content) 88 { 89 content = super.next; 90 return content.ptr !is null; 91 } 92 93 /*********************************************************************** 94 95 Scanner implementation for this iterator. Find a '\n', 96 and eat any immediately preceeding '\r'. 97 98 ***********************************************************************/ 99 100 protected override size_t scan (const(void)[] data) 101 { 102 auto content = (cast(const(char)*) data.ptr) [0 .. data.length]; 103 104 foreach (i, c; content) 105 if (c is '\n') 106 { 107 size_t slice = i; 108 if (i && content[i-1] is '\r') 109 --slice; 110 set (content.ptr, 0, slice, i); 111 return found (i); 112 } 113 114 return notFound; 115 } 116 } 117 118 119 120 /******************************************************************************* 121 122 *******************************************************************************/ 123 124 version (unittest) 125 { 126 import ocean.io.device.Array; 127 } 128 129 unittest 130 { 131 auto p = new Lines(new Array("blah".dup)); 132 }