package water.util;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import water.exceptions.JCodeSB;
/** Tight/tiny StringBuilder wrapper.
* Short short names on purpose; so they don't obscure the printing.
* Can't believe this wasn't done long long ago. */
public final class SB implements JCodeSB<SB> {
public final StringBuilder _sb;
int _indent = 0;
public SB( ) { _sb = new StringBuilder( ); }
public SB(String s) { _sb = new StringBuilder(s); }
public SB ps( String s ) { _sb.append("\""); pj(s); _sb.append("\""); return this; }
public SB p( String s ) { _sb.append(s); return this; }
public SB p( float s ) {
if( Float.isNaN(s) )
_sb.append( "Float.NaN");
else if( Float.isInfinite(s) ) {
_sb.append(s > 0 ? "Float.POSITIVE_INFINITY" : "Float.NEGATIVE_INFINITY");
} else _sb.append(s);
return this;
}
public SB p( double s ) {
if( Double.isNaN(s) )
_sb.append("Double.NaN");
else if( Double.isInfinite(s) ) {
_sb.append(s > 0 ? "Double.POSITIVE_INFINITY" : "Double.NEGATIVE_INFINITY");
} else _sb.append(s);
return this;
}
public SB p( char s ) { _sb.append(s); return this; }
public SB p( int s ) { _sb.append(s); return this; }
public SB p( long s ) { _sb.append(s); return this; }
public SB p( boolean s) { _sb.append(s); return this; }
// Not spelled "p" on purpose: too easy to accidentally say "p(1.0)" and
// suddenly call the the autoboxed version.
public SB pobj( Object s ) { _sb.append(s.toString()); return this; }
public SB i( int d ) { for( int i=0; i<d+_indent; i++ ) p(" "); return this; }
public SB i( ) { return i(0); }
public SB ip(String s) { return i().p(s); }
public SB s() { _sb.append(' '); return this; }
// Java specific append of double
public SB pj( double s ) {
if (Double.isInfinite(s))
_sb.append("Double.").append(s>0? "POSITIVE_INFINITY" : "NEGATIVE_INFINITY");
else if (Double.isNaN(s))
_sb.append("Double.NaN");
else
_sb.append(s);
return this;
}
// Java specific append of float
public SB pj( float s ) {
if (Float.isInfinite(s))
_sb.append("Float.").append(s>0? "POSITIVE_INFINITY" : "NEGATIVE_INFINITY");
else if (Float.isNaN(s))
_sb.append("Float.NaN");
else
_sb.append(s).append('f');
return this;
}
/* Append Java string - escape all " and \ */
public SB pj( String s ) { _sb.append(escapeJava(s)); return this; }
@Override
public SB pj(String objectName, String fieldName) {
_sb.append(objectName).append('.').append(fieldName);
return this;
}
public SB p( IcedBitSet ibs ) { return ibs.toString(this); }
// Increase indentation
public SB ii( int i) { _indent += i; return this; }
// Decrease indentation
public SB di( int i) { _indent -= i; return this; }
@Override
public SB ci(JCodeSB sb) {
_indent = sb.getIndent();
return this;
}
// Copy indent from given string buffer
public SB nl( ) { return p('\n'); }
// Convert a String[] into a valid Java String initializer
public SB toJavaStringInit( String[] ss ) {
if (ss==null) return p("null");
p('{');
for( int i=0; i<ss.length-1; i++ ) p('"').pj(ss[i]).p("\",");
if( ss.length > 0 ) p('"').pj(ss[ss.length-1]).p('"');
return p('}');
}
public SB toJavaStringInit( float[] ss ) {
if (ss==null) return p("null");
p('{');
for( int i=0; i<ss.length-1; i++ ) pj(ss[i]).p(',');
if( ss.length > 0 ) pj(ss[ss.length-1]);
return p('}');
}
public SB toJavaStringInit( double[] ss ) {
if (ss==null) return p("null");
p('{');
for( int i=0; i<ss.length-1; i++ ) pj(ss[i]).p(',');
if( ss.length > 0 ) pj(ss[ss.length-1]);
return p('}');
}
public SB toJavaStringInit( double[][] ss ) {
if (ss==null) return p("null");
p('{');
for( int i=0; i<ss.length-1; i++ ) toJavaStringInit(ss[i]).p(',');
if( ss.length > 0 ) toJavaStringInit(ss[ss.length-1]);
return p('}');
}
public SB toJavaStringInit( double[][][] ss ) {
if (ss==null) return p("null");
p('{');
for( int i=0; i<ss.length-1; i++ ) toJavaStringInit(ss[i]).p(',');
if( ss.length > 0 ) toJavaStringInit(ss[ss.length-1]);
return p('}');
}
public SB toJSArray(float[] nums) {
p('[');
for (int i=0; i<nums.length; i++) {
if (i>0) p(',');
p(nums[i]);
}
return p(']');
}
public SB toJSArray(String[] ss) {
p('[');
for (int i=0; i<ss.length; i++) {
if (i>0) p(',');
p('"').p(ss[i]).p('"');
}
return p(']');
}
@Override
public int getIndent() {
return _indent;
}
// Mostly a fail, since we should just dump into the same SB.
public SB p(JCodeSB sb) {
_sb.append(sb.getContent());
return this;
}
@Override public String toString() { return _sb.toString(); }
/** Java-string illegal characters which need to be escaped */
public static final Pattern[] ILLEGAL_CHARACTERS = new Pattern[] { Pattern.compile("\\",Pattern.LITERAL), Pattern.compile("\"",Pattern.LITERAL) };
public static final String[] REPLACEMENTS = new String [] { "\\\\\\\\", "\\\\\"" };
/** Escape all " and \ characters to provide a proper Java-like string
* Does not escape unicode characters.
*/
public static String escapeJava(String s) {
assert ILLEGAL_CHARACTERS.length == REPLACEMENTS.length;
for (int i=0; i<ILLEGAL_CHARACTERS.length; i++ ) {
Matcher m = ILLEGAL_CHARACTERS[i].matcher(s);
s = m.replaceAll(REPLACEMENTS[i]);
}
return s;
}
@Override
public String getContent() {
return _sb.toString();
}
}