This is an automated email from the ASF dual-hosted git repository.
rombert pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/felix-dev.git
The following commit(s) were added to refs/heads/master by this push:
new eac5f727b4 FELIX-6664 - Replacing String representation with
customized BufferedReader (#241)
eac5f727b4 is described below
commit eac5f727b49d7b109440d696a104c5cef79ca170
Author: Dominik Süß <[email protected]>
AuthorDate: Thu Nov 9 11:11:08 2023 +0100
FELIX-6664 - Replacing String representation with customized BufferedReader
(#241)
---
.../apache/felix/cm/json/io/impl/JsonSupport.java | 153 +++++++++++----------
1 file changed, 84 insertions(+), 69 deletions(-)
diff --git
a/cm.json/src/main/java/org/apache/felix/cm/json/io/impl/JsonSupport.java
b/cm.json/src/main/java/org/apache/felix/cm/json/io/impl/JsonSupport.java
index 427e675735..fe7ec3b73b 100644
--- a/cm.json/src/main/java/org/apache/felix/cm/json/io/impl/JsonSupport.java
+++ b/cm.json/src/main/java/org/apache/felix/cm/json/io/impl/JsonSupport.java
@@ -20,6 +20,7 @@ package org.apache.felix.cm.json.io.impl;
import java.io.FilterReader;
import java.io.IOException;
+import java.io.BufferedReader;
import java.io.Reader;
import java.io.StringReader;
import java.io.StringWriter;
@@ -231,80 +232,94 @@ public class JsonSupport {
* @throws IOException If something fails
*/
public static Reader createCommentRemovingReader(final Reader reader)
throws IOException {
- final String contents;
- try (final StringWriter writer = new StringWriter() ){
- final char[] buf = new char[2048];
- int l;
- while ( (l = reader.read(buf)) > 0 ) {
- writer.write(buf, 0, l);
- }
- writer.flush();
- contents = writer.toString();
+ return new CommentRemovingReader(reader);
+ }
+
+ /**
+ * Helper class to create a BufferedReader that implicitly removes inline
and blockcomments from the input
+ */
+ private static class CommentRemovingReader extends FilterReader {
+
+ private boolean closed = false;
+ private boolean insideComment = false;
+ private boolean insideLineComment = false;
+
+ public CommentRemovingReader(Reader reader) {
+ super(new BufferedReader(reader));
}
- final StringReader stringReader = new
StringReader(removeComments(contents));
- return new FilterReader(stringReader) {
- boolean closed = false;
- @Override
- public void close() throws IOException {
- if (!closed) {
- closed = true;
- reader.close();
- super.close();
+ @Override
+ public int read() throws IOException {
+ return 0;
+ }
+
+ @Override
+ public int read(char[] cbuf, int off, int len) throws IOException {
+ int charsRead = super.read(cbuf, off, len);
+ if (charsRead > 0) {
+ StringBuilder filteredContent = new StringBuilder();
+ StringBuilder currentLine = new StringBuilder();
+
+
+ for (int i = off; i < off + charsRead; i++) {
+ char c = cbuf[i];
+
+ // Handle comments
+ if (!insideComment && c == '/') {
+ if (i < off + charsRead - 1) {
+ if (cbuf[i + 1] == '*') {
+ insideComment = true;
+ i++; // Skip '*' character
+ continue;
+ } else if (cbuf[i + 1] == '/') {
+ insideLineComment = true;
+ i++; // Skip '/' character
+ continue;
+ }
+ }
+ }
+
+ //if inside a multiline comment, count newlines
+ if (insideComment && !insideLineComment && c == '\n') {
+ currentLine.append(c);
+ continue;
+ }
+
+ // Skip characters inside multiline comments
+ if (insideComment && c == '*' && i < off + charsRead -
1 && cbuf[i + 1] == '/') {
+ insideComment = false;
+ i++; // Skip '/' character
+ continue;
+ }
+
+ // Skip characters inside single-line comments
+ if (insideLineComment && c == '\n') {
+ insideLineComment = false;
+ }
+
+ // Preserve characters outside comments
+ if (!insideComment && !insideLineComment) {
+ currentLine.append(c);
+ }
+ }
+
+ filteredContent.append(currentLine.toString());
+
+ char[] filteredChars =
filteredContent.toString().toCharArray();
+ int filteredLen = Math.min(filteredChars.length, len);
+ System.arraycopy(filteredChars, 0, cbuf, off, filteredLen);
+ return filteredLen;
}
- }
- };
- }
+ return charsRead;
+ }
- /**
- * Helper method to remove comments from JSON
- * @param comments The JSON with comments
- * @return The JSON without comments
- */
- private static String removeComments(final String comments) {
- final StringBuilder sb = new StringBuilder(comments);
- int index = 0;
- boolean insideQuote = false;
- while ( index < sb.length()) {
- switch ( sb.charAt(index) ) {
- case '"' : if ( index == 0 || sb.charAt(index - 1) != '\\') {
- insideQuote = !insideQuote;
- }
- index++;
- break;
- case '/' : if ( !insideQuote && index + 1 < sb.length()) {
- if ( sb.charAt(index + 1) == '/') {
- // line comment
- int m = index + 2;
- while ( m < sb.length() && sb.charAt(m) != '\n'
) {
- m++;
- }
- sb.delete(index, m);
- } else if ( sb.charAt(index + 1 ) == '*') {
- // block comment
- int m = index + 2;
- int newlines = 0;
- while ( m < sb.length() && (sb.charAt(m) != '/'
|| sb.charAt(m - 1) != '*')) {
- if ( sb.charAt(m) == '\n') {
- newlines++;
- }
- m++;
- }
- if ( m == sb.length() ) {
- index = m; // invalid - just go to the end
- } else {
- sb.delete(index, m+1);
- for(int x = 0; x<newlines; x++) {
- sb.insert(index, '\n');
- }
- }
- }
- }
- index++;
- break;
- default: index++;
+ @Override
+ public void close() throws IOException {
+ if (!closed) {
+ closed = true;
+ in.close();
+ super.close();
}
}
- return sb.toString();
}
}