Commonize into PathUtils; On Linux/BSD try to use xdg-open/x-www-browser if Java...
[SquirrelJME.git] / buildSrc / src / main / java / cc / squirreljme / plugin / util / CommentReader.java
blob0586b6437c993c04c59f636b474f1bbbff806b6a
1 // -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
2 // ---------------------------------------------------------------------------
3 // SquirrelJME
4 // Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
5 // ---------------------------------------------------------------------------
6 // SquirrelJME is under the GNU General Public License v3+, or later.
7 // See license.mkd for licensing and copyright information.
8 // ---------------------------------------------------------------------------
10 package cc.squirreljme.plugin.util;
12 import java.io.BufferedReader;
13 import java.io.IOException;
14 import java.io.InputStream;
15 import java.io.InputStreamReader;
16 import java.io.Reader;
17 import java.io.UnsupportedEncodingException;
19 /**
20 * This is used to read comments from a source code file.
22 * @since 2020/02/22
24 public class CommentReader
25 extends Reader
27 /** The source reader. */
28 protected final BufferedReader source;
30 /** Extra character queue. */
31 private final StringBuilder _queue =
32 new StringBuilder();
34 /** Line remainder. */
35 private final StringBuilder _remainder =
36 new StringBuilder();
38 /** Are we in multi-line comment? */
39 private boolean _inMultiLine;
41 /**
42 * Initializes the comment reader.
44 * @param __in The input source.
45 * @throws NullPointerException On null arguments.
46 * @since 2020/02/22
48 public CommentReader(InputStream __in)
49 throws NullPointerException
51 try
53 this.source = new BufferedReader(
54 new InputStreamReader(__in, "utf-8"));
56 catch (UnsupportedEncodingException e)
58 throw new RuntimeException("UTF-8 is not supported?", e);
62 /**
63 * {@inheritDoc}
64 * @since 2020/02/22
66 @Override
67 public void close()
68 throws IOException
70 this.source.close();
73 /**
74 * {@inheritDoc}
75 * @since 2002/02/22
77 @Override
78 public int read(char[] __c, int __o, int __l)
79 throws IndexOutOfBoundsException, IOException
81 if (__o < 0 || __l < 0 || (__o + __l) < 0 || (__o + __l) > __c.length)
82 throw new IndexOutOfBoundsException();
84 BufferedReader source = this.source;
85 StringBuilder queue = this._queue;
86 StringBuilder remainder = this._remainder;
87 boolean inMultiLine = this._inMultiLine;
89 // Constantly try to fill the output buffer
90 int putCount = 0;
91 while (putCount < __l)
93 // If there are characters in the queue, drain from it
94 if (queue.length() > 0)
96 // Extract the first character
97 char ch = queue.charAt(0);
98 queue.deleteCharAt(0);
100 // Place it in the output
101 __c[__o++] = ch;
102 putCount++;
104 // Try again
105 continue;
108 // Read the next source line
109 String ln = (remainder.length() > 0 ? remainder.toString() :
110 source.readLine());
111 if (ln == null)
112 return (putCount > 0 ? putCount : -1);
114 // Always trim lines to remove extra clutter
115 ln = ln.trim();
117 // Always clear the remainder, since we might push it again later
118 remainder.setLength(0);
120 // The length of the line
121 int len = ln.length();
123 // Are we in a multi-line comment still?
124 if (inMultiLine)
126 // This is likely a JavaDoc continuation so drop that
127 if (ln.startsWith("* "))
128 ln = ln.substring(2);
130 // Length may have changed so recalculate it
131 len = ln.length();
133 // Find end of line
134 int eml = ln.indexOf("*/");
136 // There are no ending slashes, use entire line
137 if (eml < 0)
138 queue.append(ln);
140 // Otherwise our multi-line is going to end and we need to
141 // process the remainder of the line
142 else
144 // Add starting chunk to the queue for output
145 queue.append(ln, 0, eml);
147 // Store the remainder of the line since we may still have
148 // another comment on it
149 remainder.append(ln, eml + 2, len);
151 // Stop being in multi-line mode
152 inMultiLine = false;
156 // Normal line
157 else
159 // Get potential start positions of lines
160 int sng = ln.indexOf("//");
161 int mul = ln.indexOf("/*");
163 // Detect double star for JavaDoc
164 if (mul >= 0)
166 int jdoc = ln.indexOf("/**", mul);
167 if (jdoc >= 0)
168 mul = jdoc;
171 // No comment on this line
172 if (sng < 0 && mul < 0)
173 continue;
175 // Single line comment
176 if (sng >= 0 && (mul < 0 || sng < mul))
178 // Add fragment to the queue
179 queue.append(ln, sng + 2, len);
182 // Multi-line comment
183 else
185 // Does the multi-line end on the same line?
186 int eml = ln.indexOf("*/", mul + 2);
187 if (eml > mul)
189 // Add the comment area to the queue
190 queue.append(ln, mul + 2, eml);
192 // Add the rest of the line to the remainder for
193 // later processing
194 remainder.append(ln, eml + 2, len);
197 // Does not, so keep reading
198 else
200 // Now in a multi-line
201 inMultiLine = true;
203 // Add our comment into the queue
204 queue.append(ln, mul + 2, len);
210 // Store comment type for later runs
211 this._inMultiLine = inMultiLine;
213 // Return the number out placed characters
214 return putCount;
218 * Reads the entire file to a string.
220 * @param __sb The input buffer to write to.
221 * @return {@code __sb}.
222 * @throws IOException On read errors.
223 * @throws NullPointerException On null arguments.
224 * @since 2020/02/22
226 public final StringBuilder readAll(StringBuilder __sb)
227 throws IOException, NullPointerException
229 if (__sb == null)
230 throw new NullPointerException();
232 char[] buf = new char[512];
233 for (;;)
235 int rc = this.read(buf, 0, 512);
237 if (rc < 0)
238 break;
240 __sb.append(buf, 0, rc);
243 return __sb;
247 * The type of comment being parsed.
249 * @since 2020/02/22
251 private enum CommentType
253 /** No comment. */
254 NONE,
256 /** Single line comment. */
257 SINGLE,
259 /** Block comment. */
260 BLOCK,
262 /** End. */