Skip to content

Commit c682e2c

Browse files
authored
Merge pull request killme2008#6 from killme2008/feature/2.3.4
Feature/2.3.4
2 parents 358bc86 + 7b11573 commit c682e2c

File tree

7 files changed

+232
-41
lines changed

7 files changed

+232
-41
lines changed

pom.xml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,8 +86,8 @@
8686
<groupId>org.apache.maven.plugins</groupId>
8787
<artifactId>maven-compiler-plugin</artifactId>
8888
<configuration>
89-
<source>1.5</source>
90-
<target>1.5</target>
89+
<source>1.6</source>
90+
<target>1.6</target>
9191
<encoding>UTF-8</encoding>
9292
</configuration>
9393
</plugin>

src/main/java/com/googlecode/aviator/AviatorEvaluator.java

Lines changed: 58 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,6 @@
8787
*
8888
*/
8989
public final class AviatorEvaluator {
90-
private static Boolean trace = Boolean.valueOf(System.getProperty("aviator.asm.trace", "false"));
9190

9291
// The classloader to define generated class
9392
@Deprecated
@@ -103,35 +102,65 @@ public final class AviatorEvaluator {
103102
*/
104103
public static final int EVAL = 1;
105104

106-
// optimize level
107-
private static int optimize = EVAL;
108-
109105
/**
110106
* Aviator version
111107
*/
112108
public static final String VERSION = "2.1.1";
113109

114110
/**
115-
* Generated java class version,default 1.5
111+
* Generated java class version,default 1.6
116112
*/
117-
public static int BYTECODE_VER = Opcodes.V1_5;
113+
public static int BYTECODE_VER = Opcodes.V1_6;
118114

119115
private static OutputStream traceOutputStream = System.out;
120116

121-
/**
122-
* Default match context for decimal.
123-
*/
124-
private static MathContext mathContext = MathContext.DECIMAL128;
117+
private static final ConcurrentHashMap<Options, Object> options = new ConcurrentHashMap<Options, Object>();
125118

126119

127120
/**
128121
* Configure whether to trace code generation
129122
*
123+
* @deprecated please use {@link #setOption(Options, Object)}
130124
* @param t
131125
* true is to trace,default is false.
132126
*/
133127
public static void setTrace(boolean t) {
134-
trace = t;
128+
setOption(Options.TRACE, t);
129+
}
130+
131+
132+
/**
133+
* Adds a evaluator option
134+
*
135+
* @since 2.3.4
136+
* @see Options
137+
* @param opt
138+
* @param val
139+
*/
140+
public static void setOption(Options opt, Object val) {
141+
if (opt == null || val == null) {
142+
throw new IllegalArgumentException("Option and value should not be null.");
143+
}
144+
if (!opt.isValidValue(val)) {
145+
throw new IllegalArgumentException("Invalid value for option:" + opt.name());
146+
}
147+
options.put(opt, val);
148+
}
149+
150+
151+
/**
152+
* Returns the current evaluator option value, returns null if missing.
153+
*
154+
* @param opt
155+
* @return
156+
*/
157+
@SuppressWarnings("unchecked")
158+
public static <T> T getOption(Options opt) {
159+
Object val = options.get(opt);
160+
if (val == null) {
161+
val = opt.getDefaultValue();
162+
}
163+
return (T) val;
135164
}
136165

137166

@@ -149,24 +178,26 @@ public static OutputStream getTraceOutputStream() {
149178
* Returns current math context for decimal.
150179
*
151180
* @since 2.3.0
181+
* @deprecated Please use {@link #getOption(Options)}
152182
* @return
153183
*/
154184
public static MathContext getMathContext() {
155-
return mathContext;
185+
return getOption(Options.MATH_CONTEXT);
156186
}
157187

158188

159189
/**
160190
* Set math context for decimal.
161191
*
162192
* @param mathContext
193+
* @deprecated please use {@link #setOption(Options, Object)}
163194
* @since 2.3.0
164195
*/
165196
public static void setMathContext(MathContext mathContext) {
166197
if (mathContext == null) {
167198
throw new IllegalArgumentException("null mathContext");
168199
}
169-
AviatorEvaluator.mathContext = mathContext;
200+
setOption(Options.MATH_CONTEXT, mathContext);
170201
}
171202

172203

@@ -270,14 +301,15 @@ public AviatorClassLoader run() {
270301
*
271302
* @see #COMPILE
272303
* @see #EVAL
304+
* @deprecated please use {@link #setOption(Options, Object)}
273305
*
274306
* @param value
275307
*/
276308
public static void setOptimize(int value) {
277309
if (value != COMPILE && value != EVAL) {
278310
throw new IllegalArgumentException("Invlaid optimize option value");
279311
}
280-
optimize = value;
312+
setOption(Options.OPTIMIZE_LEVEL, value);
281313
}
282314

283315

@@ -469,17 +501,24 @@ private static Expression innerCompile(final String expression, boolean cached)
469501
}
470502

471503

504+
private static int getOptimizeLevel() {
505+
return getOption(Options.OPTIMIZE_LEVEL);
506+
}
507+
508+
472509
private static CodeGenerator newCodeGenerator(boolean cached) {
473-
switch (optimize) {
510+
switch (getOptimizeLevel()) {
474511
case COMPILE:
475512
ASMCodeGenerator asmCodeGenerator =
476-
new ASMCodeGenerator(getAviatorClassLoader(cached), traceOutputStream, trace);
513+
new ASMCodeGenerator(getAviatorClassLoader(cached), traceOutputStream,
514+
(Boolean) getOption(Options.TRACE));
477515
asmCodeGenerator.start();
478516
return asmCodeGenerator;
479517
case EVAL:
480-
return new OptimizeCodeGenerator(getAviatorClassLoader(cached), traceOutputStream, trace);
518+
return new OptimizeCodeGenerator(getAviatorClassLoader(cached), traceOutputStream,
519+
(Boolean) getOption(Options.TRACE));
481520
default:
482-
throw new IllegalArgumentException("Unknow option " + optimize);
521+
throw new IllegalArgumentException("Unknow option " + getOptimizeLevel());
483522
}
484523

485524
}
@@ -506,7 +545,7 @@ public static Expression compile(String expression) {
506545
* @return
507546
*/
508547
public static Object exec(String expression, Object... values) {
509-
if (optimize != EVAL) {
548+
if (getOptimizeLevel() != EVAL) {
510549
throw new IllegalStateException("Aviator evaluator is not in EVAL mode.");
511550
}
512551
Expression compiledExpression = compile(expression, true);
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
package com.googlecode.aviator;
2+
3+
import java.math.MathContext;
4+
5+
6+
/**
7+
* Aviator Evaluator Configuration options.
8+
*
9+
* @author dennis
10+
*
11+
*/
12+
public enum Options {
13+
/**
14+
* Always use double as BigDecimal, default is false.
15+
*
16+
* @since 2.3.4
17+
*/
18+
ALWAYS_USE_DOUBLE_AS_DECIMAL,
19+
20+
/**
21+
* Optimize level, default is {@link AviatorEvaluator#EVA}
22+
*
23+
* @see AviatorEvaluator#EVAL
24+
* @see AviatorEvaluator#COMPILE
25+
*/
26+
OPTIMIZE_LEVEL,
27+
28+
/**
29+
* Math context for decimal, default is {@link MathContext.DECIMAL128}
30+
*
31+
* @see MathContext
32+
*/
33+
MATH_CONTEXT,
34+
35+
/**
36+
* Whether to trace code generation,default is false.
37+
*/
38+
TRACE;
39+
40+
public boolean isValidValue(Object val) {
41+
switch (this) {
42+
case ALWAYS_USE_DOUBLE_AS_DECIMAL:
43+
case TRACE:
44+
return val instanceof Boolean;
45+
case OPTIMIZE_LEVEL:
46+
return (val instanceof Integer)
47+
&& (((Integer) val).intValue() == AviatorEvaluator.EVAL || ((Integer) val).intValue() == AviatorEvaluator.COMPILE);
48+
case MATH_CONTEXT:
49+
return val instanceof MathContext;
50+
}
51+
return false;
52+
}
53+
54+
55+
/**
56+
* Returns the default value of option.
57+
*
58+
* @return
59+
*/
60+
public Object getDefaultValue() {
61+
switch (this) {
62+
case ALWAYS_USE_DOUBLE_AS_DECIMAL:
63+
return false;
64+
case OPTIMIZE_LEVEL:
65+
return AviatorEvaluator.EVAL;
66+
case MATH_CONTEXT:
67+
return MathContext.DECIMAL128;
68+
case TRACE:
69+
return Boolean.valueOf(System.getProperty("aviator.asm.trace", "false"));
70+
}
71+
return null;
72+
}
73+
}

src/main/java/com/googlecode/aviator/lexer/ExpressionLexer.java

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,13 @@
2020

2121
import java.math.BigDecimal;
2222
import java.math.BigInteger;
23+
import java.math.MathContext;
2324
import java.text.CharacterIterator;
2425
import java.text.StringCharacterIterator;
2526
import java.util.Stack;
2627

2728
import com.googlecode.aviator.AviatorEvaluator;
29+
import com.googlecode.aviator.Options;
2830
import com.googlecode.aviator.exception.CompileExpressionErrorException;
2931
import com.googlecode.aviator.lexer.token.CharToken;
3032
import com.googlecode.aviator.lexer.token.NumberToken;
@@ -82,7 +84,7 @@ public void prevChar() {
8284
}
8385

8486
static final char[] VALID_HEX_CHAR = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'a', 'B', 'b', 'C',
85-
'c', 'D', 'd', 'E', 'e', 'F', 'f' };
87+
'c', 'D', 'd', 'E', 'e', 'F', 'f' };
8688

8789

8890
public boolean isValidHexChar(char ch) {
@@ -236,15 +238,23 @@ else if (hasDot) {
236238
|| this.peek == 'M' || this.peek == 'N');
237239
Number value;
238240
if (isBigDecimal) {
239-
String lexeme = this.getBigNumberLexeme(sb);
240-
value = new BigDecimal(lexeme, AviatorEvaluator.getMathContext());
241+
value =
242+
new BigDecimal(this.getBigNumberLexeme(sb),
243+
(MathContext) AviatorEvaluator.getOption(Options.MATH_CONTEXT));
241244
}
242245
else if (isBigInt) {
243-
String lexeme = this.getBigNumberLexeme(sb);
244-
value = new BigInteger(lexeme);
246+
value = new BigInteger(this.getBigNumberLexeme(sb));
245247
}
246248
else if (hasDot) {
247-
value = dval;
249+
boolean alwaysUseDecimalAsDouble = AviatorEvaluator.getOption(Options.ALWAYS_USE_DOUBLE_AS_DECIMAL);
250+
if (alwaysUseDecimalAsDouble) {
251+
value =
252+
new BigDecimal(sb.toString(),
253+
(MathContext) AviatorEvaluator.getOption(Options.MATH_CONTEXT));
254+
}
255+
else {
256+
value = dval;
257+
}
248258
}
249259
else {
250260
// if the long value is out of range,then it must be negative,so
@@ -311,7 +321,6 @@ else if (hasDot) {
311321
return token;
312322
}
313323

314-
315324
private String getBigNumberLexeme(StringBuffer sb) {
316325
String lexeme = sb.toString();
317326
lexeme = lexeme.substring(0, lexeme.length() - 1);

src/test/java/com/googlecode/aviator/AviatorEvaluatorUnitTest.java

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import static org.junit.Assert.assertNotSame;
2424
import static org.junit.Assert.assertSame;
2525

26+
import java.math.MathContext;
2627
import java.util.HashMap;
2728
import java.util.Map;
2829

@@ -45,6 +46,30 @@ public void testCompileWithoutCache() {
4546
}
4647

4748

49+
@Test
50+
public void testDefaultOptionValues() {
51+
assertEquals(AviatorEvaluator.getOption(Options.TRACE), false);
52+
assertEquals(AviatorEvaluator.getOption(Options.ALWAYS_USE_DOUBLE_AS_DECIMAL), false);
53+
assertEquals(AviatorEvaluator.getOption(Options.OPTIMIZE_LEVEL), AviatorEvaluator.EVAL);
54+
assertEquals(AviatorEvaluator.getOption(Options.MATH_CONTEXT), MathContext.DECIMAL128);
55+
}
56+
57+
58+
@Test
59+
public void testSetOptions() {
60+
try {
61+
AviatorEvaluator.setOption(Options.TRACE, true);
62+
assertEquals(AviatorEvaluator.getOption(Options.TRACE), true);
63+
AviatorEvaluator.setOption(Options.OPTIMIZE_LEVEL, AviatorEvaluator.COMPILE);
64+
assertEquals(AviatorEvaluator.getOption(Options.OPTIMIZE_LEVEL), AviatorEvaluator.COMPILE);
65+
}
66+
finally {
67+
AviatorEvaluator.setOption(Options.TRACE, false);
68+
AviatorEvaluator.setOption(Options.OPTIMIZE_LEVEL, AviatorEvaluator.EVAL);
69+
}
70+
}
71+
72+
4873
@Test
4974
public void testExec() {
5075
String exp1 = "b-c+a";

src/test/java/com/googlecode/aviator/lexer/ExpressionLexerUnitTest.java

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@
2828

2929
import org.junit.Test;
3030

31+
import com.googlecode.aviator.AviatorEvaluator;
32+
import com.googlecode.aviator.Options;
3133
import com.googlecode.aviator.exception.CompileExpressionErrorException;
3234
import com.googlecode.aviator.lexer.token.Token;
3335
import com.googlecode.aviator.lexer.token.Token.TokenType;
@@ -215,6 +217,23 @@ public void testParseNumbers() {
215217
}
216218

217219

220+
@Test
221+
public void testParseDoubleAsDecimal() {
222+
try {
223+
AviatorEvaluator.setOption(Options.ALWAYS_USE_DOUBLE_AS_DECIMAL, true);
224+
this.lexer = new ExpressionLexer("3.2");
225+
Token<?> token = this.lexer.scan();
226+
assertEquals(TokenType.Number, token.getType());
227+
assertTrue(token.getValue(null) instanceof BigDecimal);
228+
assertEquals(new BigDecimal("3.2"), token.getValue(null));
229+
assertEquals(0, token.getStartIndex());
230+
}
231+
finally {
232+
AviatorEvaluator.setOption(Options.ALWAYS_USE_DOUBLE_AS_DECIMAL, false);
233+
}
234+
}
235+
236+
218237
@Test
219238
public void testParseLikeHexNumber() {
220239
this.lexer = new ExpressionLexer("0344");

0 commit comments

Comments
 (0)