Used EOLWriter to normalize line breaks instead of regex

This commit is contained in:
Vhati 2014-03-09 03:44:40 -04:00
parent 725ba55731
commit f6dfab2748
3 changed files with 117 additions and 19 deletions

View file

@ -9,6 +9,7 @@ Changelog
- Changed modman.exe to fail rather than use VirtualStore - Changed modman.exe to fail rather than use VirtualStore
- Added modman_admin.exe, which always runs as administrator - Added modman_admin.exe, which always runs as administrator
- Added a Validate warning for junk files whose names end with a tilde - Added a Validate warning for junk files whose names end with a tilde
- Minor optimizations to reduce memory usage
1.4: 1.4:
- Cleaned up some dodgy code when initially prompting for FTL's location - Cleaned up some dodgy code when initially prompting for FTL's location

View file

@ -0,0 +1,83 @@
package net.vhati.modmanager.core;
import java.io.FilterWriter;
import java.io.IOException;
import java.io.Writer;
/**
* A filter that replaces \r, \n, or \r\n, with a standard EOL string.
*
* Essentially, s.replaceAll( "\r(?!\n)|(?<!\r)\n|\r\n", eol );
*
* Filters can be chained to share one destination buffer, while each regex
* call creates and returns a new string.
*/
public class EOLWriter extends FilterWriter {
private String eol;
private boolean sawCR = false;
/**
* Creates a new EOLWriter.
*
* @param out a Writer object to provide the underlying stream
* @param eol the string to substitute where line breaks occur
*/
public EOLWriter( Writer out, String eol ) {
super( out );
this.eol = eol;
}
@Override
public void write( int c ) throws IOException {
if ( c == '\r' ) {
this.out.write( eol );
sawCR = true;
}
else if ( c == '\n' ) {
// If in the middle of \r\n, don't bother adding another eol.
if ( !sawCR ) this.out.write( eol );
sawCR = false;
}
else {
this.out.write( c );
sawCR = false;
}
}
@Override
public void write( char cbuf[], int off, int len ) throws IOException {
int end = off + len;
for ( int i=off; i < end; i++ ) {
if ( cbuf[i] == '\r' ) {
this.out.write( cbuf, off, i-off ); // Write everything up to here.
off = i + 1; // Skip this char.
this.out.write( eol ); // Write EOL instead.
sawCR = true;
}
else if ( cbuf[i] == '\n' ) {
this.out.write( cbuf, off, i-off ); // Write everything up to here.
off = i + 1; // Skip this char.
if ( sawCR ) {
sawCR = false;
} else {
this.out.write( eol ); // Write EOL instead.
}
}
else {
sawCR = false; // Keep scanning for breaks.
}
}
if ( off < end ) { // Write all remaining chars.
this.out.write( cbuf, off, end-off );
}
}
@Override
public void write( String str, int off, int len ) throws IOException {
write( str.toCharArray(), off, len );
}
}

View file

@ -10,7 +10,7 @@ import java.io.IOException;
import java.io.OutputStream; import java.io.OutputStream;
import java.io.OutputStreamWriter; import java.io.OutputStreamWriter;
import java.io.StringReader; import java.io.StringReader;
import java.io.StringWriter; import java.io.Writer;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.nio.charset.CharacterCodingException; import java.nio.charset.CharacterCodingException;
import java.nio.charset.Charset; import java.nio.charset.Charset;
@ -176,16 +176,20 @@ public class ModUtilities {
String dstText = decodeText( dstStream, dstDescription ).text; String dstText = decodeText( dstStream, dstDescription ).text;
dstText = xmlDeclPtn.matcher(dstText).replaceFirst( "" ); dstText = xmlDeclPtn.matcher(dstText).replaceFirst( "" );
StringBuilder buf = new StringBuilder( srcText.length() +100+ dstText.length() ); // Concatenate, filtering the stream to standardize newlines and encode.
buf.append( "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" ); //
buf.append( dstText ); CharsetEncoder encoder = Charset.forName( "UTF-8" ).newEncoder();
buf.append( "\n\n<!-- Appended by Slipstream -->\n\n" ); ByteArrayOutputStream tmpData = new ByteArrayOutputStream();
buf.append( srcText ); Writer writer = new EOLWriter( new BufferedWriter( new OutputStreamWriter( tmpData, encoder ) ), "\r\n" );
buf.append( "\n" );
String mergedString = Pattern.compile("\n").matcher( buf ).replaceAll("\r\n"); writer.append( "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" );
writer.append( dstText );
writer.append( "\n\n<!-- Appended by Slipstream -->\n\n" );
writer.append( srcText );
writer.append( "\n" );
writer.flush();
InputStream result = new ByteArrayInputStream( tmpData.toByteArray() );
InputStream result = encodeText( mergedString, "UTF-8", srcDescription+"+"+dstDescription );
return result; return result;
} }
@ -227,12 +231,17 @@ public class ModUtilities {
patcher.setGlobalPanic( globalPanic ); patcher.setGlobalPanic( globalPanic );
Document mergedDoc = patcher.patch( mainDoc, appendDoc ); Document mergedDoc = patcher.patch( mainDoc, appendDoc );
StringWriter writer = new StringWriter(); // Bake XML into text, filtering the stream to standardize newlines and encode.
SloppyXMLOutputProcessor.sloppyPrint( mergedDoc, writer, encoding ); // TODO: sloppyPrint() needs EOL normalizing!?
String mergedString = writer.toString(); //
mergedString = mergedString.replaceAll( "\r(?!\n)|(?<!\r)\n|\r\n", "\r\n" ); // sloppyPrint needs normalizing!? CharsetEncoder encoder = Charset.forName( encoding ).newEncoder();
ByteArrayOutputStream tmpData = new ByteArrayOutputStream();
Writer writer = new EOLWriter( new BufferedWriter( new OutputStreamWriter( tmpData, encoder ) ), "\r\n" );
SloppyXMLOutputProcessor.sloppyPrint( mergedDoc, writer, encoding );
writer.flush();
InputStream result = new ByteArrayInputStream( tmpData.toByteArray() );
InputStream result = encodeText( mergedString, encoding, mainDescription+"+"+appendDescription );
return result; return result;
} }
@ -262,12 +271,17 @@ public class ModUtilities {
Document doc = parseStrictOrSloppyXML( srcText, srcDescription+" (wrapped)" ); Document doc = parseStrictOrSloppyXML( srcText, srcDescription+" (wrapped)" );
srcText = null; srcText = null;
StringWriter writer = new StringWriter(); // Bake XML into text, filtering the stream to standardize newlines and encode.
SloppyXMLOutputProcessor.sloppyPrint( doc, writer, encoding ); // TODO: sloppyPrint() needs EOL normalizing!?
String resultString = writer.toString(); //
resultString = resultString.replaceAll( "\r(?!\n)|(?<!\r)\n|\r\n", "\r\n" ); // sloppyPrint needs normalizing!? CharsetEncoder encoder = Charset.forName( encoding ).newEncoder();
ByteArrayOutputStream tmpData = new ByteArrayOutputStream();
Writer writer = new EOLWriter( new BufferedWriter( new OutputStreamWriter( tmpData, encoder ) ), "\r\n" );
SloppyXMLOutputProcessor.sloppyPrint( doc, writer, encoding );
writer.flush();
InputStream result = new ByteArrayInputStream( tmpData.toByteArray() );
InputStream result = encodeText( resultString, encoding, srcDescription+" (cleaned)" );
return result; return result;
} }