Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 2 additions & 4 deletions quickfixj-base/src/main/java/quickfix/FieldMap.java
Original file line number Diff line number Diff line change
Expand Up @@ -572,11 +572,9 @@ int calculateChecksum() {
if (!groupList.isEmpty()) {
if(IS_STRING_EQUIVALENT) {
String value = NumbersCache.get(entry.getKey());
for (int i = value.length(); i-- != 0;)
result += value.charAt(i);
result += MessageUtils.checksum(value, 0, value.length());
value = NumbersCache.get(groupList.size());
for (int i = value.length(); i-- != 0;)
result += value.charAt(i);
result += MessageUtils.checksum(value, 0, value.length());
result += '=' + 1;
} else {
final IntField groupField = new IntField(entry.getKey());
Expand Down
5 changes: 1 addition & 4 deletions quickfixj-base/src/main/java/quickfix/Message.java
Original file line number Diff line number Diff line change
Expand Up @@ -213,10 +213,7 @@ private static void setBodyLength(StringBuilder stringBuilder) {

private static void setChecksum(StringBuilder stringBuilder) {
int checkSumIndex = stringBuilder.lastIndexOf(CHECKSUM_FIELD);
int checkSum = 0;
for(int i = checkSumIndex; i-- != 0;)
checkSum += stringBuilder.charAt(i);
String checkSumValue = NumbersCache.get((checkSum + 1) & 0xFF); // better than sum % 256 since it avoids overflow issues
String checkSumValue = NumbersCache.get(MessageUtils.checksum(stringBuilder, 0, checkSumIndex + 1));
checkSumIndex += CHECKSUM_FIELD.length();
stringBuilder.replace(checkSumIndex + (3 - checkSumValue.length()), checkSumIndex + 3, checkSumValue);
}
Expand Down
14 changes: 9 additions & 5 deletions quickfixj-base/src/main/java/quickfix/MessageUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -292,17 +292,21 @@ public static int checksum(byte[] data, boolean isEntireMessage) {
*/
public static int checksum(Charset charset, String data, boolean isEntireMessage) {
if (CharsetSupport.isStringEquivalent(charset)) { // optimization - skip charset encoding
int sum = 0;
int end = isEntireMessage ? data.lastIndexOf("\00110=") : -1;
int len = end > -1 ? end + 1 : data.length();
for (int i = 0; i < len; i++) {
sum += data.charAt(i);
}
return sum & 0xFF; // better than sum % 256 since it avoids overflow issues
return checksum(data, 0, len);
}
return checksum(data.getBytes(charset), isEntireMessage);
}

static int checksum(CharSequence data, int start, int end) {
int sum = 0;
for (int i = start; i < end; i++) {
sum += data.charAt(i);
}
return sum & 0xFF; // better than sum % 256 since it avoids overflow issues
}

/**
* Calculates the checksum for the given message
* (excluding existing checksum field, if one exists).
Expand Down
10 changes: 10 additions & 0 deletions quickfixj-base/src/test/java/quickfix/FieldMapTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -78,4 +78,14 @@ public void testRemoveGroup() {
map.removeGroup(73);
assertFalse(map.hasGroup(73));
}

@Test
public void testGroupChecksumMatchesMessageUtils() {
FieldMap map = new Message();
Group group = new Group(73, 11);
group.setString(11, "A");
map.addGroup(group);

assertEquals(MessageUtils.checksum("73=1\00111=A\001"), map.calculateChecksum());
}
}
21 changes: 21 additions & 0 deletions quickfixj-base/src/test/java/quickfix/MessageUtilsTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.fail;

import java.nio.charset.StandardCharsets;

import org.junit.Test;

/**
Expand Down Expand Up @@ -112,4 +115,22 @@ public void testGetStringFieldWithBadValue() throws Exception {
assertNull(MessageUtils.getStringField(messageString, 10));
}

@Test
public void testStringEquivalentChecksumMatchesStringBuilderFastPath() {
String messageString = "8=FIX.4.2\0019=12\00135=X\001108=30\00110=049\001";
int checksumFieldIndex = messageString.lastIndexOf("\00110=");
StringBuilder messageBuilder = new StringBuilder(messageString);

assertEquals(MessageUtils.checksum(messageString), MessageUtils.checksum(messageBuilder, 0,
checksumFieldIndex + 1));
}

@Test
public void testMultibyteChecksumUsesEncodedBytes() {
String messageString = "8=FIX.4.2\0019=18\00135=X\00158=\u6D4B\u9A8C\00110=000\001";

assertEquals(MessageUtils.checksum(messageString.getBytes(StandardCharsets.UTF_8), true),
MessageUtils.checksum(StandardCharsets.UTF_8, messageString, true));
}

}
Loading