Browse Source

handle number formats with no required digits

git-svn-id: https://svn.code.sf.net/p/jackcess/code/jackcess/branches/jdk8@1273 f203690c-595d-4dc9-a70b-905162fa7fd2
tags/jackcess-3.0.0
James Ahlborn 5 years ago
parent
commit
7e01bae3cd

+ 57
- 12
src/main/java/com/healthmarketscience/jackcess/impl/expr/FormatUtil.java View File

@@ -169,6 +169,7 @@ public class FormatUtil
private static final char EXP_e_CHAR = 'e';
private static final char PLUS_CHAR = '+';
private static final char MINUS_CHAR = '-';
private static final char REQ_DIGIT_CHAR = '0';
private static final int NO_CHAR = -1;

private static final byte FCT_UNKNOWN = 0;
@@ -554,7 +555,8 @@ public class FormatUtil
private static void addCustomGeneralFormat(String[] fmtStrs, int fmtIdx,
StringBuilder sb)
{
addCustomNumberFormat(fmtStrs, NO_EXP_TYPES, NO_FMT_TYPES, fmtIdx, sb);
addCustomNumberFormat(fmtStrs, NO_EXP_TYPES, NO_FMT_TYPES, NO_FMT_TYPES,
fmtIdx, sb);
}

private static Fmt parseCustomDateFormat(ExprBuf buf, Args args) {
@@ -735,6 +737,7 @@ public class FormatUtil
NumberFormatter.NotationType[] expTypes =
new NumberFormatter.NotationType[NUM_NF_FMTS];
boolean[] hasFmts = new boolean[NUM_NF_FMTS];
boolean[] hasReqDigit = new boolean[NUM_NF_FMTS];

BUF_LOOP:
while(buf.hasNext()) {
@@ -773,7 +776,8 @@ public class FormatUtil
break BUF_LOOP;
}
flushPendingNumberLiteral(pendingLiteral, sb);
addCustomNumberFormat(fmtStrs, expTypes, hasFmts, fmtIdx++, sb);
addCustomNumberFormat(fmtStrs, expTypes, hasFmts, hasReqDigit,
fmtIdx++, sb);
break;
default:
pendingLiteral.append(c);
@@ -808,6 +812,11 @@ public class FormatUtil
pendingLiteral.append(c);
}
break;
case REQ_DIGIT_CHAR:
hasReqDigit[fmtIdx] = true;
flushPendingNumberLiteral(pendingLiteral, sb);
sb.append(c);
break;
default:
// most number format chars pass straight through
flushPendingNumberLiteral(pendingLiteral, sb);
@@ -822,19 +831,24 @@ public class FormatUtil
// fill in remaining formats
while(fmtIdx < NUM_NF_FMTS) {
flushPendingNumberLiteral(pendingLiteral, sb);
addCustomNumberFormat(fmtStrs, expTypes, hasFmts, fmtIdx++, sb);
addCustomNumberFormat(fmtStrs, expTypes, hasFmts, hasReqDigit,
fmtIdx++, sb);
}

return new CustomNumberFmt(
createCustomNumberFormat(fmtStrs, expTypes, hasFmts, NF_POS_IDX, args),
createCustomNumberFormat(fmtStrs, expTypes, hasFmts, NF_NEG_IDX, args),
createCustomNumberFormat(fmtStrs, expTypes, hasFmts, NF_ZERO_IDX, args),
createCustomNumberFormat(fmtStrs, expTypes, hasFmts, NF_NULL_IDX, args));
createCustomNumberFormat(fmtStrs, expTypes, hasFmts, hasReqDigit,
NF_POS_IDX, false, args, buf),
createCustomNumberFormat(fmtStrs, expTypes, hasFmts, hasReqDigit,
NF_NEG_IDX, false, args, buf),
createCustomNumberFormat(fmtStrs, expTypes, hasFmts, hasReqDigit,
NF_ZERO_IDX, true, args, buf),
createCustomNumberFormat(fmtStrs, expTypes, hasFmts, hasReqDigit,
NF_NULL_IDX, true, args, buf));
}

private static void addCustomNumberFormat(
String[] fmtStrs, NumberFormatter.NotationType[] expTypes,
boolean[] hasFmts, int fmtIdx, StringBuilder sb)
boolean[] hasFmts, boolean[] hasReqDigit, int fmtIdx, StringBuilder sb)
{
if(sb.length() == 0) {
// do special empty format handling on a per-format-type basis
@@ -844,12 +858,14 @@ public class FormatUtil
sb.append('-').append(fmtStrs[NF_POS_IDX]);
expTypes[NF_NEG_IDX] = expTypes[NF_POS_IDX];
hasFmts[NF_NEG_IDX] = hasFmts[NF_POS_IDX];
hasReqDigit[NF_NEG_IDX] = hasReqDigit[NF_POS_IDX];
break;
case NF_ZERO_IDX:
// re-use "pos" format
sb.append(fmtStrs[NF_POS_IDX]);
expTypes[NF_ZERO_IDX] = expTypes[NF_POS_IDX];
hasFmts[NF_ZERO_IDX] = hasFmts[NF_POS_IDX];
hasReqDigit[NF_ZERO_IDX] = hasReqDigit[NF_POS_IDX];
break;
default:
// use empty string result
@@ -892,14 +908,15 @@ public class FormatUtil

private static BDFormat createCustomNumberFormat(
String[] fmtStrs, NumberFormatter.NotationType[] expTypes,
boolean[] hasFmts, int fmtIdx, Args args) {
boolean[] hasFmts, boolean[] hasReqDigit, int fmtIdx,
boolean isZeroFmt, Args args, ExprBuf buf) {

String fmtStr = fmtStrs[fmtIdx];
if(!hasFmts[fmtIdx]) {
// convert the literal string to a dummy number format
if(fmtStr.length() > 0) {
// strip quoting
StringBuilder sb = new StringBuilder(fmtStr)
StringBuilder sb = buf.getScratchBuffer().append(fmtStr)
.deleteCharAt(fmtStr.length() - 1)
.deleteCharAt(0);
if(sb.length() > 0) {
@@ -927,8 +944,36 @@ public class FormatUtil
}

if(expType != null) {
return new BaseBDFormat(
new NumberFormatter.ScientificFormat(df, expType));
NumberFormat nf = new NumberFormatter.ScientificFormat(df, expType);
if(isZeroFmt) {
return new LiteralBDFormat(nf.format(BigDecimal.ZERO));
}
return new BaseBDFormat(nf);
}

if(!hasReqDigit[fmtIdx]) {
// java likes to force extra 0's while access doesn't
df.setMinimumIntegerDigits(0);
}

if(isZeroFmt) {

String zeroVal = df.format(BigDecimal.ZERO);
if(!hasReqDigit[fmtIdx]) {
// java forces a 0 but access doesn't. delete any 0 chars which were
// inserted by the java format
int prefLen = df.getPositivePrefix().length();
int len = zeroVal.length() - df.getPositiveSuffix().length();
StringBuilder sb = buf.getScratchBuffer().append(zeroVal);
for(int i = len - 1; i >= prefLen; --i) {
if(sb.charAt(i) == '0') {
sb.deleteCharAt(i);
}
}
zeroVal = sb.toString();
}

return new LiteralBDFormat(zeroVal);
}

return new DecimalBDFormat(df);

+ 13
- 4
src/test/java/com/healthmarketscience/jackcess/impl/expr/DefaultFunctionsTest.java View File

@@ -472,11 +472,20 @@ public class DefaultFunctionsTest extends TestCase

assertEvalFormat("'#'",
"13", "13",
"0", "0.003",
"", "0.003",
"-45", "-45",
"0", "-0.003"
// FIXME
// "", "0"
"", "-0.003",
"", "0"
);

assertEvalFormat("'\\0\\[#.#\\]\\0'",
"0[13.]0", "13",
"0[.]0", "0.003",
"0[.3]0", "0.3",
"-0[45.]0", "-45",
"0[.]0", "-0.003",
"-0[.3]0", "-0.3",
"0[.]0", "0"
);

assertEvalFormat("\"#;n'g;'\"",

Loading…
Cancel
Save