Skip to content

Commit 71811d0

Browse files
authored
Cleaned up conversion of int and long in converters (#551)
* Cleaned up conversion of `int` and `long` in converters * Added tests for Integer.MAX_VALUE and MIN_VALUE
1 parent 0cb4aa8 commit 71811d0

File tree

4 files changed

+74
-21
lines changed

4 files changed

+74
-21
lines changed

quickfixj-core/src/main/java/quickfix/field/converter/AbstractDateTimeConverter.java

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -65,14 +65,6 @@ protected static void throwFieldConvertError(String value, String type)
6565
throw new FieldConvertError("invalid UTC " + type + " value: " + value);
6666
}
6767

68-
protected static long parseLong(String s) {
69-
long n = 0;
70-
for (int i = 0; i < s.length(); i++) {
71-
n = (n * 10) + (s.charAt(i) - '0');
72-
}
73-
return n;
74-
}
75-
7668
protected DateFormat createDateFormat(String format) {
7769
SimpleDateFormat sdf = new SimpleDateFormat(format);
7870
sdf.setTimeZone(TimeZone.getTimeZone("UTC"));

quickfixj-core/src/main/java/quickfix/field/converter/IntConverter.java

Lines changed: 51 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
public final class IntConverter {
2828

2929
/**
30-
* Convert and integer to a String
30+
* Convert an integer to a String
3131
*
3232
* @param i the integer to convert
3333
* @return the String representing the integer
@@ -42,7 +42,8 @@ public static String convert(int i) {
4242
*
4343
* @param value the String to convert
4444
* @return the converted integer
45-
* @throws FieldConvertError raised if the String does not represent a valid integer
45+
* @throws FieldConvertError raised if the String does not represent a valid
46+
* integer
4647
* @see java.lang.Integer#parseInt(String)
4748
*/
4849
public static int convert(String value) throws FieldConvertError {
@@ -57,4 +58,52 @@ public static int convert(String value) throws FieldConvertError {
5758
throw new FieldConvertError("invalid integral value: " + value + ": " + e);
5859
}
5960
}
61+
62+
/**
63+
* Please note that input needs to be validated first, otherwise unexpected
64+
* results may occur. Please also note that this method has no range or overflow
65+
* check, so please only use it when you are sure that no overflow might occur
66+
* (e.g. for parsing seconds or smaller integers).
67+
*
68+
* @param value the String to convert
69+
* @param off offset position from which String should be parsed
70+
* @param len length to parse
71+
* @return the converted int
72+
*/
73+
static int parseInt(String value, int off, int len) {
74+
int num = 0;
75+
boolean negative = false;
76+
for (int index = 0; index < len; index++) {
77+
final char charAt = value.charAt(off + index);
78+
if (index == 0 && charAt == '-') {
79+
negative = true;
80+
continue;
81+
}
82+
num = (num * 10) + charAt - '0';
83+
}
84+
return negative ? -num : num;
85+
}
86+
87+
/**
88+
* Please note that input needs to be validated first, otherwise unexpected
89+
* results may occur. Please also note that this method has no range or overflow
90+
* check, so please only use it when you are sure that no overflow might occur
91+
* (e.g. for parsing seconds or smaller integers).
92+
*
93+
* @param value the String to convert
94+
* @return the converted long
95+
*/
96+
static long parseLong(String value) {
97+
long num = 0;
98+
boolean negative = false;
99+
for (int index = 0; index < value.length(); index++) {
100+
final char charAt = value.charAt(index);
101+
if (index == 0 && charAt == '-') {
102+
negative = true;
103+
continue;
104+
}
105+
num = (num * 10) + (value.charAt(index) - '0');
106+
}
107+
return negative ? -num : num;
108+
}
60109
}

quickfixj-core/src/main/java/quickfix/field/converter/UtcTimestampConverter.java

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/** *****************************************************************************
1+
/*******************************************************************************
22
* Copyright (c) quickfixengine.org All rights reserved.
33
*
44
* This file is part of the QuickFIX FIX Engine
@@ -15,7 +15,7 @@
1515
*
1616
* Contact ask@quickfixengine.org if any conditions of this licensing
1717
* are not clear to you.
18-
***************************************************************************** */
18+
******************************************************************************/
1919
package quickfix.field.converter;
2020

2121
import quickfix.UtcTimestampPrecision;
@@ -120,7 +120,7 @@ public static Date convert(String value) throws FieldConvertError {
120120
long timeOffset = getTimeOffsetSeconds(value);
121121
if (value.length() >= LENGTH_INCL_MILLIS) { // format has already been verified
122122
// accept up to picosenconds but parse only up to milliseconds
123-
timeOffset += parseLong(value.substring(18, LENGTH_INCL_MILLIS));
123+
timeOffset += IntConverter.parseLong(value.substring(18, LENGTH_INCL_MILLIS));
124124
}
125125
return new Date(getMillisForDay(value) + timeOffset);
126126
}
@@ -160,11 +160,7 @@ public static LocalDateTime convertToLocalDateTime(String value) throws FieldCon
160160
}
161161

162162
private static int parseInt(String value, int off, int len) {
163-
int num = 0;
164-
for (int index = 0; index < len; index++) {
165-
num = (num * 10) + value.charAt(off + index) - '0';
166-
}
167-
return num;
163+
return IntConverter.parseInt(value, off, len);
168164
}
169165

170166
private static Long getMillisForDay(String value) {
@@ -173,9 +169,9 @@ private static Long getMillisForDay(String value) {
173169
}
174170

175171
private static long getTimeOffsetSeconds(String value) {
176-
return (parseLong(value.substring(9, 11)) * 3600000L)
177-
+ (parseLong(value.substring(12, 14)) * 60000L)
178-
+ (parseLong(value.substring(15, LENGTH_INCL_SECONDS)) * 1000L);
172+
return (IntConverter.parseLong(value.substring(9, 11)) * 3600000L)
173+
+ (IntConverter.parseLong(value.substring(12, 14)) * 60000L)
174+
+ (IntConverter.parseLong(value.substring(15, LENGTH_INCL_SECONDS)) * 1000L);
179175
}
180176

181177
private static void verifyFormat(String value) throws FieldConvertError {

quickfixj-core/src/test/java/quickfix/FieldConvertersTest.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,8 @@ public class FieldConvertersTest {
5353

5454
@Test
5555
public void testIntegerConversion() throws Exception {
56+
String intMaxValuePlus3 = "2147483650";
57+
String intMinValueMinus3 = "-2147483651";
5658
assertEquals("123", IntConverter.convert(123));
5759
assertEquals(123, IntConverter.convert("123"));
5860
assertEquals(-1, IntConverter.convert("-1"));
@@ -75,6 +77,20 @@ public void testIntegerConversion() throws Exception {
7577
} catch (FieldConvertError e) {
7678
// expected
7779
}
80+
// this should fail and not overflow
81+
try {
82+
IntConverter.convert(intMaxValuePlus3);
83+
fail();
84+
} catch (FieldConvertError e) {
85+
// expected
86+
}
87+
// this should fail and not overflow
88+
try {
89+
IntConverter.convert(intMinValueMinus3);
90+
fail();
91+
} catch (FieldConvertError e) {
92+
// expected
93+
}
7894
}
7995

8096
@Test

0 commit comments

Comments
 (0)