blob: 720dde0b123ee081a13dff8edf1175513ceaa492 [file] [log] [blame]
Stuart McCulloch39cc9ac2012-07-16 13:43:38 +00001package aQute.bnd.properties;
Stuart McCullochd4826102012-06-26 16:34:24 +00002
Stuart McCulloch39cc9ac2012-07-16 13:43:38 +00003import static aQute.bnd.properties.LineType.*;
Stuart McCullochd4826102012-06-26 16:34:24 +00004
5public class PropertiesLineReader {
6
7 private final IDocument document;
8 private final int lineCount;
9
10 private int lineNum = 0;
11
12 private IRegion lastRegion = null;
13 private String lastKey = null;
14 private String lastValue = null;
15
16 public PropertiesLineReader(IDocument document) {
17 this.document = document;
18 this.lineCount = document.getNumberOfLines();
19 }
20
21 public PropertiesLineReader(String data) {
22 this(new Document(data));
23 }
24
25 public LineType next() throws Exception {
26 int index = 0;
27 char[] chars = null;
28
29 StringBuilder keyData = new StringBuilder();
30 StringBuilder valueData = new StringBuilder();
31 StringBuilder currentBuffer = keyData;
32
33 boolean started = false;
34
35 mainLoop: while (true) {
36 if (chars == null)
37 chars = grabLine(false);
38 if (chars == null)
39 return eof;
40
41 if (index >= chars.length)
42 break;
43
44 char c = chars[index];
45 if (c == '\\') {
46 index++;
47 if (index == chars.length) {
48 chars = grabLine(true);
49 index = 0;
50 if (chars == null || chars.length == 0)
51 break; // The last line ended with a backslash
52 }
53 currentBuffer.append(chars[index]);
54 index++;
55 continue mainLoop;
56 }
57
58 if (c == '=' || c == ':')
59 currentBuffer = valueData;
60
61 if (!started && (c == '#' || c == '!'))
62 return comment;
63
64 if (Character.isWhitespace(c)) {
65 if (started) {
66 // whitespace ends the key
67 currentBuffer = valueData;
68 }
69 } else {
70 started = true;
71 currentBuffer.append(c);
72 }
73
74 index++;
75 }
76
77 if (!started)
78 return blank;
79
80 lastKey = keyData.toString();
81 return entry;
82 }
83
84 private char[] grabLine(boolean continued) throws BadLocationException {
85 if (lineNum >= lineCount) {
86 lastRegion = null;
87 return null;
88 }
89
90 IRegion lineInfo = document.getLineInformation(lineNum);
91 char[] chars = document.get(lineInfo.getOffset(), lineInfo.getLength()).toCharArray();
92
93 if (continued) {
94 int length = lastRegion.getLength();
95 length += document.getLineDelimiter(lineNum - 1).length();
96 length += lineInfo.getLength();
97 lastRegion = new Region(lastRegion.getOffset(), length);
98 } else {
99 lastRegion = lineInfo;
100 }
101
102 lineNum++;
103 return chars;
104 }
105
106 public IRegion region() {
107 if (lastRegion == null)
108 throw new IllegalStateException("Last region not available: either before start or after end of document.");
109 return lastRegion;
110 }
111
112 public String key() {
113 if (lastKey == null)
114 throw new IllegalStateException(
115 "Last key not available: either before state or after end of document, or last line type was not 'entry'.");
116 return lastKey;
117 }
118
119 public String value() {
120 if (lastValue == null)
121 throw new IllegalStateException(
122 "Last value not available: either before state or after end of document, or last line type was not 'entry'.");
123 return lastValue;
124 }
125}