/* * Copyright © 2008-2011 Rebecca G. Bettencourt / Kreative Software * <p> * The contents of this file are subject to the Mozilla Public License * Version 1.1 (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at * <a href="http://www.mozilla.org/MPL/">http://www.mozilla.org/MPL/</a> * <p> * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the * License for the specific language governing rights and limitations * under the License. * <p> * Alternatively, the contents of this file may be used under the terms * of the GNU Lesser General Public License (the "LGPL License"), in which * case the provisions of LGPL License are applicable instead of those * above. If you wish to allow use of your version of this file only * under the terms of the LGPL License and not to allow others to use * your version of this file under the MPL, indicate your decision by * deleting the provisions above and replace them with the notice and * other provisions required by the LGPL License. If you do not delete * the provisions above, a recipient may use your version of this file * under either the MPL or the LGPL License. * @since KSFL 1.0 * @author Rebecca G. Bettencourt, Kreative Software */ package com.kreative.cff; import java.io.Serializable; import java.io.DataInput; import java.io.DataOutput; import java.io.IOException; public class FieldSpec implements Serializable { private static final long serialVersionUID = 1L; public static final FieldSpec DATA = new FieldSpec(FieldType.DATA, FieldSize.DATA); private FieldType type; private FieldSize size; private boolean littleEndian; public FieldSpec(FieldType type, FieldSize size) { this.type = type; this.size = size; this.littleEndian = false; } public FieldSpec(FieldType type, FieldSize size, boolean littleEndian) { this.type = type; this.size = size; this.littleEndian = littleEndian; } public FieldSpec(String spec) { this.type = null; this.size = null; this.littleEndian = false; spec = spec.trim(); if (spec.length() > 0) this.type = FieldType.forChar(spec.charAt(0)); if (this.type == null) this.type = FieldType.CHARACTER_TYPE; if (spec.length() > 1) this.size = FieldSize.forChar(spec.charAt(1)); if (this.size == null) this.size = ((this.type == FieldType.DATA) ? FieldSize.DATA : FieldSize.MEDIUM); if (spec.length() > 2) switch (spec.charAt(2)) { case 'L': case 'l': case 'I': case 'i': this.littleEndian = true; break; case 'B': case 'b': case 'M': case 'm': this.littleEndian = false; break; } } public FieldSpec(byte spec) { this.type = FieldType.forBitPattern(spec); if (this.type == null) this.type = FieldType.CHARACTER_TYPE; this.size = FieldSize.forBitPattern(spec); if (this.size == null) this.size = ((this.type == FieldType.DATA) ? FieldSize.DATA : FieldSize.MEDIUM); this.littleEndian = ((spec & 0x80) != 0); } public FieldType type() { return type; } public FieldSize size() { return size; } public boolean littleEndian() { return littleEndian; } public boolean bigEndian() { return !littleEndian; } public int byteCount() { return size.byteCount(); } public int bitCount() { return size.bitCount(); } public Class<? extends Number> nativeType() { return size.nativeType(); } public String stringRepresentation() { String s = ""+type.canonicalCharRepresentation(); if (size.nativeType() != null) { s += size.canonicalCharRepresentation(); if (littleEndian) s += "l"; } return s; } public byte bitPatternRepresentation() { return (byte)( type.bitPatternRepresentation() | size.bitPatternRepresentation() | (byte)(littleEndian ? (byte)0x80 : (byte)0x00) ); } public Number read(DataInput in) throws IOException { return littleEndian ? size.readLE(in) : size.readBE(in); } public void write(DataOutput out, Number n) throws IOException { if (littleEndian) size.writeLE(out, n); else size.writeBE(out, n); } public boolean equals(Object o) { return ( o instanceof FieldSpec && ((FieldSpec)o).type == type && ((FieldSpec)o).size == size && ((FieldSpec)o).littleEndian == littleEndian ); } public int hashCode() { return type.hashCode() ^ size.hashCode() ^ (littleEndian ? -1 : 0); } }