com.crankuptheamps.client.FIXBuilder Maven / Gradle / Ivy
////////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2010-2020 60East Technologies Inc., All Rights Reserved.
//
// This computer software is owned by 60East Technologies Inc. and is
// protected by U.S. copyright laws and other laws and by international
// treaties. This computer software is furnished by 60East Technologies
// Inc. pursuant to a written license agreement and may be used, copied,
// transmitted, and stored only in accordance with the terms of such
// license agreement and with the inclusion of the above copyright notice.
// This computer software or any other copies thereof may not be provided
// or otherwise made available to any other person.
//
// U.S. Government Restricted Rights. This computer software: (a) was
// developed at private expense and is in all respects the proprietary
// information of 60East Technologies Inc.; (b) was not developed with
// government funds; (c) is a trade secret of 60East Technologies Inc.
// for all purposes of the Freedom of Information Act; and (d) is a
// commercial item and thus, pursuant to Section 12.212 of the Federal
// Acquisition Regulations (FAR) and DFAR Supplement Section 227.7202,
// Government's use, duplication or disclosure of the computer software
// is subject to the restrictions set forth by 60East Technologies Inc..
//
////////////////////////////////////////////////////////////////////////////
package com.crankuptheamps.client;
import java.nio.charset.StandardCharsets;
import com.crankuptheamps.client.exception.CommandException;
/**
* Used to build up message strings for FIX.
*/
public class FIXBuilder
{
/**
* We'll repeatedly double capacity when growth is required.
* Starting at less than zero doesn't work,
* capacity won't initialize to anything less than this value.
*/
private static final int MIN_CAPACITY = 8;
private byte[] _buffer = null;
private int _size = 0;
private int _capacity = 1024;
private final byte _fieldSeparator;
public FIXBuilder(int capacity, byte fieldSeparator)
{
_fieldSeparator = fieldSeparator;
_capacity = capacity < MIN_CAPACITY ? MIN_CAPACITY : capacity;
_buffer = new byte[_capacity];
}
/**
* Clears self.
*/
public void clear()
{
_size = 0;
}
/**
* Returns the number of bytes in the byte array containing the FIX message.
*
* @return Number of valid bytes in the byte array.
*/
public int getSize()
{
return _size;
}
/**
* Returns the byte array containing the FIX message. The number of valid
* bytes within the buffer is returned from getSize().
*
* @return Byte array containing the FIX message.
*/
public byte[] getBytes()
{
return _buffer;
}
private int ruLog10(int tag)
{
long scalar = 10;
for (int j = 1; j < 20; ++j)
{
if(tag < scalar)
{
return j;
}
scalar = scalar * 10;
}
return 0;
}
private void checkCapacity(int bytesNeeded)
{
if(_capacity - _size < bytesNeeded)
{
// Not enough capacity left, must resize
while (_capacity - _size < bytesNeeded)
{
_capacity = _capacity * 2;
}
byte[] newbuf = new byte[_capacity];
System.arraycopy(_buffer, 0, newbuf, 0, _size);
_buffer = newbuf;
}
}
/**
* Appends a tag and and value pair contained within a byte buffer to the FIX message.
*
* @param tag
* The integer FIX tag to append.
* @param value
* The byte buffer containing the FIX value to append.
* @param offset
* The starting location of the value inside the byte buffer.
* @param length
* The length of the value inside the byte buffer.
* @throws IllegalArgumentException
* If the tag argument is negative.
* @throws CommandException not thrown, throws {@link IllegalArgumentException}
* @return
* A reference to this object.
*/
public FIXBuilder append(int tag, byte[] value, int offset, int length)
throws CommandException
{
if(tag < 0)
throw new IllegalArgumentException("negative tag used in FIXBuilder");
int tagSize = ruLog10(tag);
int sizeNeeded = tagSize + length + 2;
checkCapacity(sizeNeeded);
// Tag
int writeIndex = _size + tagSize;
for (int j = 1; j <= tagSize; ++j)
{
_buffer[writeIndex - j] = (byte) (48 + (tag % 10));
tag = tag / 10;
}
// Equal sign
_buffer[writeIndex] = '=';
++writeIndex;
// value
System.arraycopy(value, offset, _buffer, writeIndex, length);
writeIndex += length;
_buffer[writeIndex] = _fieldSeparator;
_size += sizeNeeded;
return this;
}
/**
* Appends a tag and value pair to contained within a byte buffer to the FIX message.
* @param tag The integer FIX to append.
* @param value The byte buffer containing the FIX value to append.
* @return A reference to this object.
* @throws CommandException error occurred while appending the tag and value to the message
*/
public FIXBuilder append(int tag, byte[] value) throws CommandException
{
return append(tag, value, 0, value.length);
}
/**
* Appends a tag and value pair to the FIX message.
*
* @param tag
* The integer FIX tag to append.
* @param value
* The FIX value for the tag to append. The value will be converted
* to an ISO-8859-1 byte array for writing.
* @throws IllegalArgumentException
* If the tag argument is negative.
* @throws CommandException
* If the tag or value argument is not convertible to ISO-8859-1
* @return A reference to this object.
*/
public FIXBuilder append(int tag, String value) throws CommandException
{
return append(tag, toBytes(value));
}
// Private methods
private static byte[] toBytes(final String datum)
{
return datum.getBytes(StandardCharsets.ISO_8859_1);
}
}