com.crankuptheamps.client.fields.StringField Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of amps-client Show documentation
Show all versions of amps-client Show documentation
AMPS Java client by 60East Technologies, Inc.
////////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2010-2021 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.fields;
import java.io.UnsupportedEncodingException;
import java.nio.BufferOverflowException;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.charset.CharsetDecoder;
import java.nio.charset.CharsetEncoder;
import java.nio.charset.CoderResult;
import com.crankuptheamps.client.CommandId;
/**
* Field data for a {@link com.crankuptheamps.client.Message} which consists of a string.
*/
public class StringField extends Field
{
protected static final String LATIN1 = "ISO-8859-1";
protected static final byte LATIN1_ZERO = 48;
private ByteBuffer value =
ByteBuffer.allocate(getConversionBufInitialSize());
private byte[] bytes = value.array();
// These are used only for quick conversion without collecting garbage
private CharBuffer charValue =
CharBuffer.allocate(getConversionBufInitialSize());
private char[] charBytes = charValue.array();
/**
* Returns the initial default size for the byte and char conversion buffers
* used by this instance. Defaults to 256 for this class.
*
* @return Returns a default size of 256.
*/
protected int getConversionBufInitialSize() { return 256; }
protected StringField(byte[] buffer, int position, int length)
{
super(buffer, position, length);
}
/**
* Default constructor.
*/
public StringField()
{
}
public StringField(String value)
{
super(value);
}
/**
* Returns a string representation of the Field value, where the bytes are interpreted by using the specified
* decoder.
* @param decoder The charset decoder used to interpret bytes as characters.
* @return a newly-constructed String representing the value of this field
*/
public String getValue(CharsetDecoder decoder)
{
if(this.buffer != null)
{
return new String(this.buffer,this.position,this.length,decoder.charset());
}
return null;
}
/**
* Writes the byte value of this instance into the specified byte buffer, if the value is not null.
* @param v The byte buffer to write in to.
* @return Return true if this instance is not null, otherwise false.
*/
public boolean getValue(ByteBuffer v)
{
if(this.buffer != null)
{
v.put(this.buffer,this.position,this.length);
return true;
}
return false;
}
/**
* Writes the byte value of this instance into the specified command ID buffer object, if the value is not null.
* @param v The command ID object to write in to.
* @return Return true if this instance is not null, otherwise false.
*/
public boolean getValue(CommandId v)
{
if(this.buffer != null)
{
v.set(this.buffer,this.position,this.length);
return true;
}
return false;
}
/**
* Sets the value of this instance with the specified region of a byte buffer. Note: the bytes are not
* copied from the buffer. The specified buffer region is referenced by this instance.
* @param v The byte buffer.
* @param offset The starting position of the value in the byte buffer.
* @param length The length from the starting position of the value in the byte buffer.
*/
public void setValue(byte[] v,int offset,int length)
{
this.buffer = v;
this.position = offset;
this.length = length;
}
/**
* Sets the value of this instance with the specified buffer from the command ID object. Note: the bytes are not
* copied from the buffer. The specified buffer region is referenced by this instance.
* @param v The command ID object whose value is used to set this instance.
*/
public void setValue(CommandId v)
{
this.buffer = v.id;
this.position = 0;
if(v.id == null)
{
this.length = 0;
} else {
this.length = v.id.length;
}
}
/**
* Sets the value of this instance from the specified string. The characters of the string are interpreted using
* the specified encoder. This method makes its own copy of the bytes.
* @param v The string used as the value.
* @param encoder The encoder used to interpret the string's characters as bytes.
*/
public void setValue(String v, CharsetEncoder encoder)
{
if(v == null)
{
reset();
return;
}
int vLength = v.length();
// Check if charbuffer conversion space needs expansion
int reqSize = charValue.capacity();
if(vLength > reqSize)
{
// Must resize
while(vLength > reqSize) reqSize *= 2;
charValue = CharBuffer.allocate(reqSize);
charBytes = charValue.array();
}
// Check if buffer storage space needs expansion
reqSize = value.capacity();
float maxBytesPerChar = encoder.maxBytesPerChar();
if(vLength*maxBytesPerChar > reqSize)
{
// Must resize
while(vLength*maxBytesPerChar > reqSize) reqSize *= 2;
value = ByteBuffer.allocate(reqSize);
bytes = value.array();
}
// Copy to the charbuffer
charValue.clear();
v.getChars(0,vLength,charBytes,0); // Turns out this method is faster than doing a put
charValue.limit(vLength);
// Encode to the byte buffer
value.clear();
encoder.reset();
try
{
CoderResult result = encoder.encode(charValue,value,true);
if(result.isError()) result.throwException();
}
catch(Exception ex)
{
throw new RuntimeException(ex);
}
set(bytes, 0, value.position());
// getBytes is faster than using a CharBuffer, however, there's a bunch of garbage
// collected in using this method, so we avoid it. (about a 7% bump in performance, but
// under heavy load it creates some GC issues.)
//try { this.buffer = v.getBytes(LATIN1); } catch(UnsupportedEncodingException e) {;}
}
}