package com.laytonsmith.core.functions;
import com.laytonsmith.PureUtilities.Version;
import com.laytonsmith.annotations.api;
import com.laytonsmith.annotations.core;
import com.laytonsmith.annotations.seealso;
import com.laytonsmith.core.CHVersion;
import com.laytonsmith.core.Static;
import com.laytonsmith.core.constructs.CBoolean;
import com.laytonsmith.core.constructs.CByteArray;
import com.laytonsmith.core.constructs.CDouble;
import com.laytonsmith.core.constructs.CInt;
import com.laytonsmith.core.constructs.CString;
import com.laytonsmith.core.constructs.CVoid;
import com.laytonsmith.core.constructs.Construct;
import com.laytonsmith.core.constructs.Target;
import com.laytonsmith.core.environments.Environment;
import com.laytonsmith.core.exceptions.CRE.CRECastException;
import com.laytonsmith.core.exceptions.CRE.CREFormatException;
import com.laytonsmith.core.exceptions.CRE.CRERangeException;
import com.laytonsmith.core.exceptions.CRE.CREThrowable;
import com.laytonsmith.core.exceptions.ConfigRuntimeException;
import java.io.UnsupportedEncodingException;
import java.nio.BufferUnderflowException;
import java.nio.ByteOrder;
/**
*
*/
@core
public class ByteArrays {
public static String docs(){
return "This class contains all the methods needed to manipulate a byte array primitive. Since"
+ " byte arrays would be very inefficient to implement using a normal array, this data type"
+ " allows for more efficient operations, while still allowing for low level data access."
+ " Most data transferred within scripts is higher level, and does not require access"
+ " to a byte array, however, code that interacts with external processes may require"
+ " use of these functions to properly manipulate the data. Note that all the methods"
+ " deal with low level types, so the following definitions apply: a byte is 8 bits,"
+ " a short is 16 bits, an int is 32 bits, a long is 64 bits. UTF-8 strings are supported"
+ " directly. The byte array is automatically resized as needed.";
}
@api
public static class byte_array extends ba {
@Override
public Class<? extends CREThrowable>[] thrown() {
return new Class[]{};
}
@Override
public Construct exec(Target t, Environment environment, Construct... args) throws ConfigRuntimeException {
return new CByteArray(t);
}
@Override
public Integer[] numArgs() {
return new Integer[]{0};
}
@Override
public String docs() {
return "byte_array {} Returns a new byte array primitive, which can be operated on with the ba_ series of functions.";
}
@Override
public CHVersion since() {
return CHVersion.V3_3_1;
}
@Override
public String getName() {
return "byte_array";
}
}
@api
public static class ba_as_array extends ba {
@Override
public Construct exec(Target t, Environment environment, Construct... args) throws ConfigRuntimeException {
CByteArray ba = Static.getByteArray(args[0], t);
return ba.asArray(t);
}
@Override
public Integer[] numArgs() {
return new Integer[]{1};
}
@Override
public String docs() {
return "array {byte_array} Returns a new read only copy of the underlying byte array. This array is much more efficient"
+ " than if the array were made manually, however, it is read only. If you need to manipulate the array's"
+ " contents, then you can clone the array, however, the returned array (and any clones) cannot be automatically"
+ " interfaced with the byte array primitives. This operation is discouraged, because normal arrays are very"
+ " inefficient for dealing with low level bit data.";
}
@Override
public CHVersion since() {
return CHVersion.V3_3_1;
}
@Override
public String getName() {
return "ba_as_array";
}
}
@api
public static class ba_rewind extends ba {
@Override
public Construct exec(Target t, Environment environment, Construct... args) throws ConfigRuntimeException {
CByteArray ba = getBA(args, t);
ba.rewind();
return CVoid.VOID;
}
@Override
public Integer[] numArgs() {
return new Integer[]{1};
}
@Override
public String docs() {
return "void {byte_array} Rewinds the byte array marker to 0.";
}
@Override
public CHVersion since() {
return CHVersion.V3_3_1;
}
@Override
public String getName() {
return "ba_rewind";
}
}
@api
public static class ba_get_byte extends ba_get {
@Override
public Construct exec(Target t, Environment environment, Construct... args) throws ConfigRuntimeException {
CByteArray ba = getBA(args, t);
Integer pos = get_getPos(args, t);
try {
return new CInt(ba.getByte(pos), t);
} catch(IndexOutOfBoundsException | BufferUnderflowException e){
throw new CRERangeException(e.getMessage(), t);
}
}
@Override
public String docs() {
return "int {byte_array, [pos]} Returns an int, read in as an 8 bit byte, from the given position, or wherever the"
+ " marker is currently at by default.";
}
@Override
public CHVersion since() {
return CHVersion.V3_3_1;
}
@Override
public String getName() {
return "ba_get_byte";
}
}
@api
public static class ba_get_char extends ba_get {
@Override
public Construct exec(Target t, Environment environment, Construct... args) throws ConfigRuntimeException {
CByteArray ba = getBA(args, t);
Integer pos = get_getPos(args, t);
try{
return new CString(ba.getChar(pos), t);
} catch(IndexOutOfBoundsException | BufferUnderflowException e){
throw new CRERangeException(e.getMessage(), t);
}
}
@Override
public String docs() {
return "string {byte_array, [pos]} Returns a one character string, read in as an 32 bit char, from the given position, or wherever the"
+ " marker is currently at by default.";
}
@Override
public CHVersion since() {
return CHVersion.V3_3_1;
}
@Override
public String getName() {
return "ba_get_char";
}
}
@api
public static class ba_get_short extends ba_get {
@Override
public Construct exec(Target t, Environment environment, Construct... args) throws ConfigRuntimeException {
CByteArray ba = getBA(args, t);
Integer pos = get_getPos(args, t);
try{
return new CInt(ba.getShort(pos), t);
} catch(IndexOutOfBoundsException | BufferUnderflowException e){
throw new CRERangeException(e.getMessage(), t);
}
}
@Override
public String docs() {
return "int {byte_array, [pos]} Returns an int, read in as a 16 bit short, from the given position, or wherever the"
+ " marker is currently at by default.";
}
@Override
public CHVersion since() {
return CHVersion.V3_3_1;
}
@Override
public String getName() {
return "ba_get_short";
}
}
@api
public static class ba_get_int extends ba_get {
@Override
public Construct exec(Target t, Environment environment, Construct... args) throws ConfigRuntimeException {
CByteArray ba = getBA(args, t);
Integer pos = get_getPos(args, t);
try{
return new CInt(ba.getInt(pos), t);
} catch(IndexOutOfBoundsException | BufferUnderflowException e){
throw new CRERangeException(e.getMessage(), t);
}
}
@Override
public String docs() {
return "int {byte_array, [pos]} Returns an int, read in as a 32 bit int, from the given position, or wherever the"
+ " marker is currently at by default.";
}
@Override
public CHVersion since() {
return CHVersion.V3_3_1;
}
@Override
public String getName() {
return "ba_get_int";
}
}
@api
public static class ba_get_long extends ba_get {
@Override
public Construct exec(Target t, Environment environment, Construct... args) throws ConfigRuntimeException {
CByteArray ba = getBA(args, t);
Integer pos = get_getPos(args, t);
try {
return new CInt(ba.getLong(pos), t);
} catch (IndexOutOfBoundsException | BufferUnderflowException e) {
throw new CRERangeException(e.getMessage(), t);
}
}
@Override
public String docs() {
return "int {byte_array, [pos]} Returns an int, read in as a 64 bit long, from the given position, or wherever the"
+ " marker is currently at by default.";
}
@Override
public CHVersion since() {
return CHVersion.V3_3_1;
}
@Override
public String getName() {
return "ba_get_long";
}
}
@api
public static class ba_get_float extends ba_get {
@Override
public Construct exec(Target t, Environment environment, Construct... args) throws ConfigRuntimeException {
CByteArray ba = getBA(args, t);
Integer pos = get_getPos(args, t);
try {
return new CDouble(ba.getFloat(pos), t);
} catch (IndexOutOfBoundsException | BufferUnderflowException e) {
throw new CRERangeException(e.getMessage(), t);
}
}
@Override
public String docs() {
return "double {byte_array, [pos]} Returns a double, read in as a 32 bit float, from the given position, or wherever the"
+ " marker is currently at by default.";
}
@Override
public CHVersion since() {
return CHVersion.V3_3_1;
}
@Override
public String getName() {
return "ba_get_float";
}
}
@api
public static class ba_get_double extends ba_get {
@Override
public Construct exec(Target t, Environment environment, Construct... args) throws ConfigRuntimeException {
CByteArray ba = getBA(args, t);
Integer pos = get_getPos(args, t);
try {
return new CDouble(ba.getDouble(pos), t);
} catch(IndexOutOfBoundsException | BufferUnderflowException e){
throw new CRERangeException(e.getMessage(), t);
}
}
@Override
public String docs() {
return "double {byte_array, [pos]} Returns a double, read in as a 64 bit double, from the given position, or wherever the"
+ " marker is currently at by default.";
}
@Override
public CHVersion since() {
return CHVersion.V3_3_1;
}
@Override
public String getName() {
return "ba_get_double";
}
}
@api
public static class ba_get_bytes extends ba_get {
@Override
public Integer[] numArgs() {
return new Integer[]{2, 3};
}
@Override
public Construct exec(Target t, Environment environment, Construct... args) throws ConfigRuntimeException {
CByteArray ba = getBA(args, t);
int size = Static.getInt32(args[1], t);
Integer pos = null;
if(args.length == 3){
pos = Static.getInt32(args[2], t);
}
try {
return ba.getBytes(size, pos);
} catch(IndexOutOfBoundsException | BufferUnderflowException e){
throw new CRERangeException(e.getMessage(), t);
}
}
@Override
public String docs() {
return "byte_array {byte_array, length, [pos]} Returns a new byte_array primitive, starting from pos (or wherever the marker is"
+ " by default) to length.";
}
@Override
public CHVersion since() {
return CHVersion.V3_3_1;
}
@Override
public String getName() {
return "ba_get_bytes";
}
}
@api
public static class ba_get_string extends ba_get {
@Override
public Construct exec(Target t, Environment environment, Construct... args) throws ConfigRuntimeException {
CByteArray ba = getBA(args, t);
Integer pos = get_getPos(args, t);
String encoding = null;
if(args.length == 3){
encoding = args[2].nval();
}
try{
return new CString(ba.readUTF8String(pos, encoding), t);
} catch(UnsupportedEncodingException e){
throw new CREFormatException(e.getMessage(), t);
} catch(IndexOutOfBoundsException | BufferUnderflowException e){
throw new CRERangeException(e.getMessage(), t);
} catch(NegativeArraySizeException e){
throw new CREFormatException("Invalid data", t);
}
}
@Override
public String docs() {
return "string {byte_array, [pos], [encoding]} Returns a UTF-8 encoded string, from the given position, or wherever the"
+ " marker is currently at by default. The string is assumed to have encoded the length of the string"
+ " with a 32 bit integer, then the string bytes. (This will be the case is the byte_array was encoded"
+ " with ba_set_string.) The encoding of the string may be set, but defaults to UTF-8.";
}
@Override
public CHVersion since() {
return CHVersion.V3_3_1;
}
@Override
public String getName() {
return "ba_get_string";
}
}
@api
public static class ba_put_byte extends ba_put {
@Override
public Construct exec(Target t, Environment environment, Construct... args) throws ConfigRuntimeException {
CByteArray ba = getBA(args, t);
byte b = Static.getInt8(args[1], t);
Integer pos = set_getPos(args, t);
ba.putByte(b, pos);
return CVoid.VOID;
}
@Override
public String docs() {
return "void {byte_array, int, [pos]} Writes an int, interpreted as an 8 bit byte, starting from the given position, or wherever the"
+ " marker is currently at by default.";
}
@Override
public CHVersion since() {
return CHVersion.V3_3_1;
}
@Override
public String getName() {
return "ba_put_byte";
}
}
@api
public static class ba_put_char extends ba_put {
@Override
public Construct exec(Target t, Environment environment, Construct... args) throws ConfigRuntimeException {
CByteArray ba = getBA(args, t);
String b = args[1].val();
char c = '\0';
if(b.length() > 0){
c = b.charAt(0);
}
Integer pos = set_getPos(args, t);
ba.putChar(c, pos);
return CVoid.VOID;
}
@Override
public String docs() {
return "void {byte_array, string, [pos]} Writes the first character of the string, interpreted as an 32 bit char, starting from the given position, or wherever the"
+ " marker is currently at by default. If the string is empty, a \\0 is written instead.";
}
@Override
public CHVersion since() {
return CHVersion.V3_3_1;
}
@Override
public String getName() {
return "ba_put_char";
}
}
@api
public static class ba_put_short extends ba_put {
@Override
public Construct exec(Target t, Environment environment, Construct... args) throws ConfigRuntimeException {
CByteArray ba = getBA(args, t);
short b = Static.getInt16(args[1], t);
Integer pos = set_getPos(args, t);
ba.putShort(b, pos);
return CVoid.VOID;
}
@Override
public String docs() {
return "void {byte_array, int, [pos]} Writes an int, interpreted as an 16 bit short, starting from the given position, or wherever the"
+ " marker is currently at by default.";
}
@Override
public CHVersion since() {
return CHVersion.V3_3_1;
}
@Override
public String getName() {
return "ba_put_short";
}
}
@api
public static class ba_put_int extends ba_put {
@Override
public Construct exec(Target t, Environment environment, Construct... args) throws ConfigRuntimeException {
CByteArray ba = getBA(args, t);
int b = Static.getInt32(args[1], t);
Integer pos = set_getPos(args, t);
ba.putInt(b, pos);
return CVoid.VOID;
}
@Override
public String docs() {
return "void {byte_array, int, [pos]} Writes an int, interpreted as a 32 bit int, starting from the given position, or wherever the"
+ " marker is currently at by default.";
}
@Override
public CHVersion since() {
return CHVersion.V3_3_1;
}
@Override
public String getName() {
return "ba_put_int";
}
}
@api
public static class ba_put_long extends ba_put {
@Override
public Construct exec(Target t, Environment environment, Construct... args) throws ConfigRuntimeException {
CByteArray ba = getBA(args, t);
long b = Static.getInt(args[1], t);
Integer pos = set_getPos(args, t);
ba.putLong(b, pos);
return CVoid.VOID;
}
@Override
public String docs() {
return "void {byte_array, int, [pos]} Writes an int, interpreted as a 64 bit, starting from the given position, or wherever the"
+ " marker is currently at by default.";
}
@Override
public CHVersion since() {
return CHVersion.V3_3_1;
}
@Override
public String getName() {
return "ba_put_long";
}
}
@api
public static class ba_put_float extends ba_put {
@Override
public Construct exec(Target t, Environment environment, Construct... args) throws ConfigRuntimeException {
CByteArray ba = getBA(args, t);
float b = Static.getDouble32(args[1], t);
Integer pos = set_getPos(args, t);
ba.putFloat(b, pos);
return CVoid.VOID;
}
@Override
public String docs() {
return "void {byte_array, double, [pos]} Writes a double, interpreted as a 32 bit float, starting from the given position, or wherever the"
+ " marker is currently at by default.";
}
@Override
public CHVersion since() {
return CHVersion.V3_3_1;
}
@Override
public String getName() {
return "ba_put_float";
}
}
@api
public static class ba_put_double extends ba_put {
@Override
public Construct exec(Target t, Environment environment, Construct... args) throws ConfigRuntimeException {
CByteArray ba = getBA(args, t);
double b = Static.getDouble(args[1], t);
Integer pos = set_getPos(args, t);
ba.putDouble(b, pos);
return CVoid.VOID;
}
@Override
public String docs() {
return "void {byte_array, double, [pos]} Writes a double, interpreted as a 64 bit double, starting from the given position, or wherever the"
+ " marker is currently at by default.";
}
@Override
public CHVersion since() {
return CHVersion.V3_3_1;
}
@Override
public String getName() {
return "ba_put_double";
}
}
@api
public static class ba_put_bytes extends ba_put {
@Override
public Construct exec(Target t, Environment environment, Construct... args) throws ConfigRuntimeException {
CByteArray dest = getBA(args, t);
CByteArray src = Static.getByteArray(args[1], t);
Integer pos = set_getPos(args, t);
dest.putBytes(src, pos);
return CVoid.VOID;
}
@Override
public String docs() {
return "void {destination_byte_array, source_byte_array, [pos]} Writes the contents of the source_byte_array into this byte array,"
+ " starting at pos, or wherever the marker is currently at by default.";
}
@Override
public CHVersion since() {
return CHVersion.V3_3_1;
}
@Override
public String getName() {
return "ba_put_bytes";
}
}
@api
public static class ba_put_string extends ba_put {
@Override
public Construct exec(Target t, Environment environment, Construct... args) throws ConfigRuntimeException {
CByteArray ba = getBA(args, t);
String s = args[1].val();
Integer pos = set_getPos(args, t);
String encoding = null;
if(args.length == 3){
encoding = args[2].nval();
}
try{
ba.writeUTF8String(s, pos, encoding);
} catch(IndexOutOfBoundsException e){
throw new CRERangeException(e.getMessage(), t);
} catch(UnsupportedEncodingException e){
throw new CREFormatException(e.getMessage(), t);
}
return CVoid.VOID;
}
@Override
public String docs() {
return "void {byte_array, string, [pos], [encoding]} Writes the length of the string to the byte array, as a short, (interpreted as UTF-8),"
+ " then writes the UTF-8 string itself. If an external application requires the string to be serialized"
+ " in a different manner, then use the string-byte_array conversion methods in StringHandling, however"
+ " strings written in this manner are compatible with ba_get_string. The encoding may be set, but defaults to UTF-8.";
}
@Override
public CHVersion since() {
return CHVersion.V3_3_1;
}
@Override
public String getName() {
return "ba_put_string";
}
}
@api
@seealso({ba_is_little_endian.class})
public static class ba_set_little_endian extends AbstractFunction {
@Override
public Class<? extends CREThrowable>[] thrown() {
return new Class[]{CRECastException.class};
}
@Override
public boolean isRestricted() {
return false;
}
@Override
public Boolean runAsync() {
return null;
}
@Override
public Construct exec(Target t, Environment environment, Construct... args) throws ConfigRuntimeException {
CByteArray ba = Static.getByteArray(args[0], t);
boolean setLittle = Static.getBoolean(args[1]);
ba.setOrder(setLittle ? ByteOrder.LITTLE_ENDIAN : ByteOrder.BIG_ENDIAN);
return CVoid.VOID;
}
@Override
public String getName() {
return "ba_set_little_endian";
}
@Override
public Integer[] numArgs() {
return new Integer[]{2};
}
@Override
public String docs() {
return "void {byte_array, setLittleEndian} Sets the byte order that the specified byte array will use"
+ " for all future gets/sets. By default, a byte array is Big Endian. If setLittleEndian is true,"
+ " the byte array will be set to little endian, otherwise it will be set to big endian.";
}
@Override
public Version since() {
return CHVersion.V3_3_1;
}
}
@api
@seealso({ba_set_little_endian.class})
public static class ba_is_little_endian extends AbstractFunction {
@Override
public Class<? extends CREThrowable>[] thrown() {
return new Class[]{CRECastException.class};
}
@Override
public boolean isRestricted() {
return false;
}
@Override
public Boolean runAsync() {
return null;
}
@Override
public Construct exec(Target t, Environment environment, Construct... args) throws ConfigRuntimeException {
CByteArray ba = Static.getByteArray(args[0], t);
return CBoolean.get(ba.getOrder() == ByteOrder.LITTLE_ENDIAN);
}
@Override
public String getName() {
return "ba_is_little_endian";
}
@Override
public Integer[] numArgs() {
return new Integer[]{1};
}
@Override
public String docs() {
return "boolean {byte_array} Returns true if this byte array is little endian. By default, byte arrays are big endian,"
+ " but this may be changed with ba_set_little_endian.";
}
@Override
public Version since() {
return CHVersion.V3_3_1;
}
}
private static CByteArray getBA(Construct [] args, Target t){
return Static.getByteArray(args[0], t);
}
private static Integer get_getPos(Construct [] args, Target t){
if(args.length == 2){
return Static.getInt32(args[1], t);
} else {
return null;
}
}
private static Integer set_getPos(Construct [] args, Target t){
if(args.length == 3){
return Static.getInt32(args[2], t);
} else {
return null;
}
}
private static abstract class ba extends AbstractFunction {
@Override
public Class<? extends CREThrowable>[] thrown() {
return new Class[]{CRECastException.class};
}
@Override
public Boolean runAsync() {
return null;
}
@Override
public boolean isRestricted() {
return false;
}
}
public static abstract class ba_put extends ba {
@Override
public Integer[] numArgs() {
return new Integer[]{2, 3};
}
}
public static abstract class ba_get extends ba {
@Override
public Class<? extends CREThrowable>[] thrown() {
return new Class[]{CRECastException.class, CRERangeException.class};
}
@Override
public Integer[] numArgs() {
return new Integer[]{1, 2};
}
}
}