Mercurial > hg > monetdb-java
comparison src/main/java/nl/cwi/monetdb/mcl/parser/HeaderLineParser.java @ 0:a5a898f6886c
Copy of MonetDB java directory changeset e6e32756ad31.
author | Sjoerd Mullender <sjoerd@acm.org> |
---|---|
date | Wed, 21 Sep 2016 09:34:48 +0200 (2016-09-21) |
parents | |
children | e67d58485172 b9b35ca2eec2 |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:a5a898f6886c |
---|---|
1 /* | |
2 * This Source Code Form is subject to the terms of the Mozilla Public | |
3 * License, v. 2.0. If a copy of the MPL was not distributed with this | |
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. | |
5 * | |
6 * Copyright 1997 - July 2008 CWI, August 2008 - 2016 MonetDB B.V. | |
7 */ | |
8 | |
9 package nl.cwi.monetdb.mcl.parser; | |
10 | |
11 | |
12 /** | |
13 * The HeaderLineParser is a generic MCLParser that extracts values from | |
14 * a metadata header in the MCL protocol either as string or integer | |
15 * values. | |
16 * | |
17 * @author Fabian Groffen <Fabian.Groffen> | |
18 */ | |
19 public class HeaderLineParser extends MCLParser { | |
20 private int type; | |
21 | |
22 public final static int NAME = 1; | |
23 public final static int LENGTH = 2; | |
24 public final static int TABLE = 3; | |
25 public final static int TYPE = 4; | |
26 | |
27 /** | |
28 * Constructs a HeaderLineParser which expects columncount columns. | |
29 * | |
30 * @param columncount the number of columns in the to be parsed string | |
31 */ | |
32 public HeaderLineParser(int columncount) { | |
33 super(columncount); | |
34 } | |
35 | |
36 /** | |
37 * Parses the given String source as header line. If source cannot | |
38 * be parsed, an MCLParseException is thrown. The columncount argument | |
39 * given during construction is used for allocation of the backing | |
40 * array. Parsing a header line with has more fields will therefore | |
41 * result in a crash. While this seems illogical, the caller should | |
42 * know this size, since the StartOfHeader contains this | |
43 * information. | |
44 * | |
45 * @param source a String which should be parsed | |
46 * @return the type of then parsed header line | |
47 * @throws MCLParseException if an error occurs during parsing | |
48 */ | |
49 @Override | |
50 public int parse(String source) throws MCLParseException { | |
51 char[] chrLine = source.toCharArray(); | |
52 int len = chrLine.length; | |
53 int pos = 0; | |
54 boolean foundChar = false; | |
55 boolean nameFound = false; | |
56 // find header name | |
57 for (int i = len - 1; i >= 0; i--) { | |
58 switch (chrLine[i]) { | |
59 case ' ': | |
60 case '\n': | |
61 case '\t': | |
62 case '\r': | |
63 if (!foundChar) { | |
64 len = i - 1; | |
65 } else { | |
66 pos = i + 1; | |
67 } | |
68 break; | |
69 case '#': | |
70 // found! | |
71 nameFound = true; | |
72 if (pos == 0) pos = i + 1; | |
73 i = 0; // force the loop to terminate | |
74 break; | |
75 default: | |
76 foundChar = true; | |
77 pos = 0; | |
78 break; | |
79 } | |
80 } | |
81 if (!nameFound) | |
82 throw new MCLParseException("invalid header, no header name found", pos); | |
83 | |
84 // depending on the name of the header, we continue | |
85 switch (chrLine[pos]) { | |
86 case 'n': | |
87 if (len - pos == 4 && | |
88 source.regionMatches(pos + 1, "name", 1, 3)) | |
89 { | |
90 getValues(chrLine, 2, pos - 3); | |
91 type = NAME; | |
92 } | |
93 break; | |
94 case 'l': | |
95 if (len - pos == 6 && | |
96 source.regionMatches(pos + 1, "length", 1, 5)) | |
97 { | |
98 getIntValues(chrLine, 2, pos - 3); | |
99 type = LENGTH; | |
100 } | |
101 break; | |
102 case 't': | |
103 if (len - pos == 4 && | |
104 source.regionMatches(pos + 1, "type", 1, 3)) | |
105 { | |
106 getValues(chrLine, 2, pos - 3); | |
107 type = TYPE; | |
108 } else if (len - pos == 10 && | |
109 source.regionMatches(pos + 1, "table_name", 1, 9)) | |
110 { | |
111 getValues(chrLine, 2, pos - 3); | |
112 type = TABLE; | |
113 } | |
114 break; | |
115 default: | |
116 throw new MCLParseException("unknown header: " + | |
117 (new String(chrLine, pos, len - pos))); | |
118 } | |
119 | |
120 // adjust colno | |
121 reset(); | |
122 | |
123 return type; | |
124 } | |
125 | |
126 /** | |
127 * Returns an array of Strings containing the values between | |
128 * ',\t' separators. Note that no quoting/dequoting is done in this | |
129 * method. | |
130 * | |
131 * @param chrLine a character array holding the input data | |
132 * @param start where the relevant data starts | |
133 * @param stop where the relevant data stops | |
134 */ | |
135 final private void getValues(char[] chrLine, int start, int stop) { | |
136 int elem = 0; | |
137 | |
138 for (int i = start + 1; i < stop; i++) { | |
139 if (chrLine[i] == '\t' && chrLine[i - 1] == ',') { | |
140 values[elem++] = | |
141 new String(chrLine, start, i - 1 - start); | |
142 start = i + 1; | |
143 } | |
144 } | |
145 // add the left over part | |
146 values[elem++] = new String(chrLine, start, stop - start); | |
147 } | |
148 | |
149 /** | |
150 * Returns an array of ints containing the values between | |
151 * ',\t' separators. | |
152 * | |
153 * @param chrLine a character array holding the input data | |
154 * @param start where the relevant data starts | |
155 * @param stop where the relevant data stops | |
156 */ | |
157 final private void getIntValues(char[] chrLine, int start, int stop) | |
158 throws MCLParseException | |
159 { | |
160 int elem = 0; | |
161 int tmp = 0; | |
162 | |
163 for (int i = start; i < stop; i++) { | |
164 if (chrLine[i] == ',' && chrLine[i + 1] == '\t') { | |
165 intValues[elem++] = tmp; | |
166 tmp = 0; | |
167 start = i++; | |
168 } else { | |
169 tmp *= 10; | |
170 // note: don't use Character.isDigit() here, because | |
171 // we only want ISO-LATIN-1 digits | |
172 if (chrLine[i] >= '0' && chrLine[i] <= '9') { | |
173 tmp += (int)chrLine[i] - (int)'0'; | |
174 } else { | |
175 throw new MCLParseException("expected a digit in " + new String(chrLine) + " at " + i); | |
176 } | |
177 } | |
178 } | |
179 // add the left over part | |
180 intValues[elem++] = tmp; | |
181 } | |
182 } |