string.format fixes
Fix string.format's floating point implementation Disable space if explicitPlus is set Disable leftAdjust and zeroPad if no width is specified precision gets set to zero if only a dot is specified Add support for %a/A, Lua can use these and Java happens to support it
This commit is contained in:
@@ -79,7 +79,6 @@ public class BaseLib extends TwoArgFunction implements ResourceFinder {
|
||||
|
||||
Globals globals;
|
||||
|
||||
|
||||
/** Perform one-time initialization on the library by adding base functions
|
||||
* to the supplied environment, and returning it as the return value.
|
||||
* @param modname the module name supplied if this is loaded via 'require'.
|
||||
|
||||
@@ -24,12 +24,8 @@ package org.luaj.vm2.lib;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
import org.luaj.vm2.Buffer;
|
||||
import org.luaj.vm2.LuaClosure;
|
||||
import org.luaj.vm2.LuaString;
|
||||
import org.luaj.vm2.LuaTable;
|
||||
import org.luaj.vm2.LuaValue;
|
||||
import org.luaj.vm2.Varargs;
|
||||
import org.luaj.vm2.*;
|
||||
import org.luaj.vm2.compat.JavaCompat;
|
||||
import org.luaj.vm2.compiler.DumpState;
|
||||
|
||||
/**
|
||||
@@ -274,6 +270,39 @@ public class StringLib extends TwoArgFunction {
|
||||
case 'f':
|
||||
case 'g':
|
||||
case 'G':
|
||||
case 'a':
|
||||
case 'A':
|
||||
double j = args.checkdouble(arg);
|
||||
if (Double.isNaN(j) || Double.isInfinite(j)) {
|
||||
String nprefix = "";
|
||||
if (JavaCompat.INSTANCE.doubleToRawLongBits(j) < 0)
|
||||
nprefix = "-";
|
||||
else if (fdsc.explicitPlus)
|
||||
nprefix = "+";
|
||||
else if (fdsc.space)
|
||||
nprefix = " ";
|
||||
String bstr = Double.isNaN(j) ? LuaDouble.JSTR_NAN : LuaDouble.JSTR_POSINF;
|
||||
if (fdsc.conversion == 'E' || fdsc.conversion == 'G')
|
||||
bstr = bstr.toUpperCase();
|
||||
fdsc.precision = -1;
|
||||
fdsc.zeroPad = false;
|
||||
fdsc.format(result, valueOf(nprefix + bstr));
|
||||
} else if ((fdsc.conversion == 'g' || fdsc.conversion == 'G') && fdsc.precision == -1) {
|
||||
//TODO: This gives a slightly different format but is better than nothing
|
||||
String nprefix = "";
|
||||
if (j >= 0) {
|
||||
if (fdsc.explicitPlus)
|
||||
nprefix = "+";
|
||||
else if (fdsc.space)
|
||||
nprefix = " ";
|
||||
}
|
||||
String bstr = Double.toString(j);
|
||||
if (fdsc.conversion == 'G')
|
||||
bstr = bstr.toUpperCase();
|
||||
else
|
||||
bstr = bstr.toLowerCase();
|
||||
fdsc.format(result, valueOf(nprefix + bstr));
|
||||
} else
|
||||
fdsc.format(result, args.checkdouble(arg));
|
||||
break;
|
||||
case 'q':
|
||||
@@ -375,8 +404,8 @@ public class StringLib extends TwoArgFunction {
|
||||
}
|
||||
}
|
||||
|
||||
precision = -1;
|
||||
if ( c == '.' ) {
|
||||
precision = 0;
|
||||
c = ( (p < n) ? strfrmt.luaByte( p++ ) : 0 );
|
||||
if ( Character.isDigit( (char) c ) ) {
|
||||
precision = c - '0';
|
||||
@@ -386,20 +415,32 @@ public class StringLib extends TwoArgFunction {
|
||||
c = ( (p < n) ? strfrmt.luaByte( p++ ) : 0 );
|
||||
}
|
||||
}
|
||||
}
|
||||
} else
|
||||
precision = -1;
|
||||
|
||||
if ( Character.isDigit( (char) c ) )
|
||||
error("invalid format (width or precision too long)");
|
||||
|
||||
if ( width == -1 ) {
|
||||
// default width overrides '-' and '0'
|
||||
leftAdjust = false;
|
||||
zeroPad = false;
|
||||
} else
|
||||
zeroPad &= !leftAdjust; // '-' overrides '0'
|
||||
space &= !explicitPlus; // '+' overrides ' '
|
||||
conversion = c;
|
||||
length = p - start;
|
||||
src = strfrmt.substring(start - 1, p).tojstring();
|
||||
}
|
||||
|
||||
public void format(Buffer buf, byte c) {
|
||||
// TODO: not clear that any of width, precision, or flags apply here.
|
||||
if (!leftAdjust)
|
||||
pad(buf, ' ', width - 1);
|
||||
|
||||
buf.append(c);
|
||||
|
||||
if (leftAdjust)
|
||||
pad(buf, ' ', width - 1);
|
||||
}
|
||||
|
||||
public void format(Buffer buf, long number) {
|
||||
@@ -430,9 +471,11 @@ public class StringLib extends TwoArgFunction {
|
||||
int ndigits = minwidth;
|
||||
int nzeros;
|
||||
|
||||
boolean allowPlusSpace = conversion == 'd' || conversion == 'i';
|
||||
|
||||
if ( number < 0 ) {
|
||||
ndigits--;
|
||||
} else if ( explicitPlus || space ) {
|
||||
} else if ( allowPlusSpace && (explicitPlus || space) ) {
|
||||
minwidth++;
|
||||
}
|
||||
|
||||
@@ -454,12 +497,26 @@ public class StringLib extends TwoArgFunction {
|
||||
buf.append( (byte)'-' );
|
||||
digits = digits.substring( 1 );
|
||||
}
|
||||
} else if ( explicitPlus ) {
|
||||
} else if ( allowPlusSpace && explicitPlus ) {
|
||||
buf.append( (byte)'+' );
|
||||
} else if ( space ) {
|
||||
} else if ( allowPlusSpace && space ) {
|
||||
buf.append( (byte)' ' );
|
||||
}
|
||||
|
||||
if (alternateForm) {
|
||||
switch (conversion) {
|
||||
case 'o':
|
||||
buf.append((byte) '0');
|
||||
break;
|
||||
case 'x':
|
||||
buf.append("0x");
|
||||
break;
|
||||
case 'X':
|
||||
buf.append("0X");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( nzeros > 0 )
|
||||
pad( buf, '0', nzeros );
|
||||
|
||||
@@ -470,14 +527,40 @@ public class StringLib extends TwoArgFunction {
|
||||
}
|
||||
|
||||
public void format(Buffer buf, double x) {
|
||||
buf.append( StringLib.this.format(src, x) );
|
||||
// TODO: Java does not support alternateForm with 'g'
|
||||
String sFormat = "%";
|
||||
if (leftAdjust)
|
||||
sFormat += ("-");
|
||||
if (explicitPlus)
|
||||
sFormat += ("+");
|
||||
if (space)
|
||||
sFormat += (" ");
|
||||
if (alternateForm && conversion != 'g' && conversion != 'G')
|
||||
sFormat += ("#");
|
||||
if (zeroPad)
|
||||
sFormat += ("0");
|
||||
if (width != -1)
|
||||
sFormat += (width);
|
||||
if (precision != -1)
|
||||
sFormat += (".") + (precision);
|
||||
sFormat += ((char) conversion);
|
||||
buf.append( StringLib.this.format(sFormat, x) );
|
||||
}
|
||||
|
||||
public void format(Buffer buf, LuaString s) {
|
||||
int nullindex = s.indexOf( (byte)'\0', 0 );
|
||||
if ( nullindex != -1 )
|
||||
s = s.substring( 0, nullindex );
|
||||
|
||||
int newLength = precision == -1 ? s.length() : Math.min(precision, s.length());
|
||||
|
||||
if (!leftAdjust)
|
||||
pad(buf, zeroPad ? '0' : ' ', width - newLength);
|
||||
|
||||
buf.append(s);
|
||||
|
||||
if (leftAdjust)
|
||||
pad(buf, ' ', width - newLength);
|
||||
}
|
||||
|
||||
public final void pad(Buffer buf, char c, int n) {
|
||||
|
||||
@@ -73,7 +73,6 @@ import org.luaj.vm2.lib.ResourceFinder;
|
||||
|
||||
public class JseBaseLib extends org.luaj.vm2.lib.BaseLib {
|
||||
|
||||
|
||||
/** Perform one-time initialization on the library by creating a table
|
||||
* containing the library functions, adding that table to the supplied environment,
|
||||
* adding the table to package.loaded, and returning table as the return value.
|
||||
|
||||
Reference in New Issue
Block a user