001package org.unix4j.io; 002 003import org.unix4j.line.Line; 004import org.unix4j.util.StringUtil; 005 006import java.util.Collection; 007import java.util.Iterator; 008import java.util.LinkedList; 009import java.util.stream.Stream; 010 011/** 012 * Input device reading the input from a string. If the string contains 013 * line-ending code (UNIX or DOS), it is split into multiple lines. 014 */ 015public class StringInput implements Input { 016 017 private final Input input; 018 019 /** 020 * Constructor with lines. Each line is tested for new line characters and 021 * possibly split into multiple lines. 022 * 023 * @param lines 024 * the lines for this input 025 */ 026 public StringInput(String... lines) { 027 this(new BufferedInput(toList(lines))); 028 } 029 030 /** 031 * Constructor with lines. Each line is tested for new line characters and 032 * possibly split into multiple lines. 033 * 034 * @param lines 035 * the lines for this input 036 */ 037 public StringInput(Iterable<? extends String> lines) { 038 this(lines instanceof Collection ? 039 new BufferedInput(toList(lines)) : 040 new IteratorInput(toIterator(lines)) 041 ); 042 } 043 044 /** 045 * Constructor with lines. Each line is tested for new line characters and 046 * possibly split into multiple lines. 047 * 048 * @param lines 049 * the lines for this input 050 */ 051 public StringInput(Stream<? extends String> lines) { 052 this(lines.iterator()); 053 } 054 055 /** 056 * Constructor with lines. Each line is tested for new line characters and 057 * possibly split into multiple lines. 058 * 059 * @param lines 060 * the lines for this input 061 */ 062 public StringInput(Iterator<? extends String> lines) { 063 this(new IteratorInput(toIterator(lines))); 064 } 065 066 private StringInput(Input input) { 067 this.input = input; 068 } 069 070 @Override 071 public boolean hasMoreLines() { 072 return input.hasMoreLines(); 073 } 074 075 @Override 076 public Line readLine() { 077 return input.readLine(); 078 } 079 080 @Override 081 public Iterator<Line> iterator() { 082 return input.iterator(); 083 } 084 085 @Override 086 public void close() { 087 input.close(); 088 } 089 090 @Override 091 public String toString() { 092 return input.toString(); 093 } 094 095 public String toMultilineString() { 096 if (input instanceof BufferedInput) { 097 return ((BufferedInput)input).toMultiLineString(); 098 } 099 return toString(); 100 } 101 102 private static LinkedList<Line> toList(String[] lines) { 103 final LinkedList<Line> list = new LinkedList<Line>(); 104 for (int i = 0; i < lines.length; i++) { 105 list.addAll(StringUtil.splitLines(lines[i])); 106 } 107 return list; 108 } 109 110 private static LinkedList<Line> toList(Iterable<? extends String> lines) { 111 final LinkedList<Line> list = new LinkedList<Line>(); 112 for (String line : lines) { 113 list.addAll(StringUtil.splitLines(line)); 114 } 115 return list; 116 } 117 118 private static Iterator<Line> toIterator(final Iterable<? extends String> lines) { 119 return toIterator(lines.iterator()); 120 } 121 122 private static Iterator<Line> toIterator(final Iterator<? extends String> lines) { 123 return new Iterator<Line>() { 124 final LinkedList<Line> next = new LinkedList<>(); 125 @Override 126 public boolean hasNext() { 127 return false; 128 } 129 130 @Override 131 public Line next() { 132 if (next.isEmpty()) { 133 if (lines.hasNext()) { 134 next.addAll(StringUtil.splitLines(lines.next())); 135 } 136 } 137 return next.isEmpty() ? null : next.removeFirst(); 138 } 139 140 @Override 141 public void remove() { 142 throw new UnsupportedOperationException("remove is not supported"); 143 } 144 }; 145 } 146}