import java.math.BigDecimal;
/*
* Dump.java
*
* Projeto ECFbabel
*
* Copyright 2005-2007 Daniel "Spanazzi" Gonçalves
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* Fornece métodos para produção de dumps hexadecimais a partir de arrays de bytes ou
* de inteiros (inteiros representando bytes sem sinal, entre 0 e 255). Um dump
* hexadecimal produzido pelo método dump(byte[])
é parecido com o
* seguinte exemplo:
*
*
* Titulo do dump aqui
* 000000 38 19 4A 14 F9 12 91 52-73 89 BA F9 F3 2E 00 CC 8.J....Rs.......
* 000010 FB 37 7A 88 35 87 30 47-39 C1 DD D6 C9 F5 1F 11 .7z.5.0G9.......
* 000020 E6 A6 C1 7D 4E 27 C1 A6-55 17 99 34 19 17 30 C9 ...}N'..U..4..0.
* 000030 CC 68 C4 2B 74 2B 83 9D-59 15 3B 86 B9 F1 9D 07 .h.+t+..Y.;.....
* 000040 9F 14 99 AE C6 A2 C6 40-EC 27 2C 55 61 F7 2A 63 .......@.',Ua.*c
* 000050 8C AD 82 22 68 11 CE 24-41 9C 8B 93 DA AA 62 3C ..."h..$A.....b<
* 000060 C5 17 BD 49 6F 19 E4 F7-9D 3B 4C 33 14 15 81 66 ...Io....;L3...f
* 000070 97 BA A4 29 70 B2 81 04-35 08 AA 6D 8D 6E 6F 54 ...)p...5..m.noT
* 000080 9C DA 6A 28 F6 B4 C2 D7-BD 01 D0 6C D7 CC 8D 04 ..j(.......l....
* 000090 29 BA 0F 87 21 B2 99 52-7B E5 19 5C 4D F7 6A 32 )...!..R{..\M.j2
* 0000A0 36 A4 77 58 33 67 54 EF-C0 62 3F 19 29 D6 A7 A2 6.wX3gT..b?.)...
* 0000B0 77 54 B0 3E DE 3E 83 1B-FE 22 4E EF 8C F7 99 88 wT.>.>..."N.....
* 0000C0 55 6B CE 9E 75 A3 50 B7-FA A5 59 2A 41 34 7D 56 Uk..u.P...Y*A4}V
* 0000D0 FA E6 FD 0A 77 36 C5 52-C4 E3 ....w6.R..
* Dump: 218 byte(s)
*
*
* Também fornece diversos métodos convenientes para log de dumps hexadecimais.
*
* @since Outubro/2007
*
* @version $Id: Dump.java,v 1.1.1.1 2008/03/12 03:29:34 rawfosgod Exp $
*
* @author Daniel Gonçalves
*/
public final class Dump {
/**
* Constrói um buffer string contendo um dumping hexadecimal do array de
* inteiros.
*
* @param data array de inteiros. Cada elemento do array deverá ser um valor
* que represente um byte sem sinal, entre 0 e 255, inclusive.
*/
public static String dump(final int[] data) {
return dump(ByteUtils.itob(data));
}
/**
* Constrói um buffer string contendo um dumping hexadecimal do array de
* bytes especificado.
*
* @param data array de dados.
*
* @return buffer string contendo o dump hexadecimal.
*/
public static String dump(final byte[] data) {
String eol = System.getProperty("line.separator");
StringBuilder buffer = new StringBuilder();
int offset = 0;
int column = 0;
StringBuilder hexDump = new StringBuilder();
StringBuilder chrDump = new StringBuilder();
for (int pos = 0; pos < data.length; pos++) {
hexDump.append(hex((int)(data[pos] & 0xff), 2));
chrDump.append(chr((int)(data[pos] & 0xff)));
column++;
if (column > 15) {
buffer.append(" ")
.append(hex(offset, 6)) .append(" ")
.append(hexDump) .append(" ")
.append(chrDump) .append(eol);
column = 0;
offset += 16;
hexDump = new StringBuilder();
chrDump = new StringBuilder();
}
else {
if (column == 8) {
// inclui um separador "-" entre a 8a. e 9a. colunas
hexDump.append("-");
}
else {
// separa com 1 espaço os valores hexadecimais dos bytes
hexDump.append(" ");
}
}
}
if ((column != 0) && (column < 15)) {
// completa a linha com espaços até a 16a. posição
while (column < 16) {
hexDump.append(" "); // 3 espaços
chrDump.append(" "); // 1 espaço
column++;
}
// remove o último espaço da sequência
hexDump.deleteCharAt(hexDump.length()-1);
buffer.append(" ")
.append(hex(offset, 6)) .append(" ")
.append(hexDump) .append(" ")
.append(chrDump) .append(eol);
}
// inclui o rodapé, indicando o total de bytes no dump
buffer.append(" Dump: ").append(data.length).append(" byte(s).").append(eol);
return buffer.toString();
} // dump(byte[])
/**
* Retorna uma string de tamanho fixo, contendo a representação hexadecimal do valor.
*
* @param value valor inteiro, de base 10, a ser convertido para base 16.
*
* @param length comprimento total desejado.
*
* @return Representação hexadecimal do valor com o comprimento especificado.
* A string resultante será completada com zeros à esquerda até que o
* comprimento total desejado seja atingido.
* Se a representação hexadecimal do valor resultar em um comprimento maior
* que o especificado, a string resultante será formada de asteriscos,
* indicando que o comprimento especificado não foi suficiente para o valor.
*/
public static String hex(final int value, final int length) {
StringBuilder str = new StringBuilder(Integer.toString(value, 16).toUpperCase());
if (str.length() < length) {
int falta = (length - str.length());
for (int i = 1; i <= falta; i++) {
str.insert(0, "0");
}
}
else if (str.length() > length) {
str = new StringBuilder();
for (int i = 1; i <= length; i++) {
str.append("*");
}
}
return str.toString();
}
private static String chr(final int value) {
if ((value < 32) || (value > 127)) {
return ".";
}
return new String(new byte[] { (byte)(value & 0xff) });
}
} // {{{ Dump }}}
/*
* ByteUtils.java
*
* Projeto ECFbabel
*
* Copyright 2005-2007 Daniel "Spanazzi" Gonçalves
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* TODO: documentar!
*
* @since Setembro/2007
*
* @version $Id: ByteUtils.java,v 1.1.1.1 2008/03/12 03:29:33 rawfosgod Exp $
*
* @author Daniel Gonçalves
*/
final class ByteUtils {
private ByteUtils() {}
/**
* Retorna o byte de baixa ordem a partir de um valor inteiro.
*
* @param value valor inteiro (até 65535).
*
* @return byte de baixa ordem do valor. Por exemplo, o byte de
* baixa ordem para o valor 1234 é 210.
*/
public static int lo(final int value) {
int low = value;
if (value > 255) low = Math.abs(value % 256);
return low;
}
/**
* Retorna o byte de alta ordem a partir de um valor inteiro.
*
* @param value valor inteiro (até 65535).
*
* @return byte de alta ordem do valor. Por exemplo, o byte de
* alta ordem para o valor 1234 é 4.
*/
public static int hi(final int value) {
int high = 0;
if (value > 255) high = Math.abs((int)(value / 256));
return high;
}
/**
* Converte 2 bytes sem sinal no formato Intel Low/High para um inteiro.
* Como no exemplo:
*
*
* int valor = 1234; // '100 1101 0010'
* int hi = ByteUtils.hi(valor); // resulta: 4 '100'
* int lo = ByteUtils.lo(valor); // resulta: 210 '1101 0010'
* int test = ByteUtils.hilo2int(hi, lo) // resulta: 1234 '100 1101 0010'
*
*
* @param high byte de alta ordem (deve ser um valor entre 0 e 255 inclusive).
* @param low byte de baixa ordem (deve ser um valor entre 0 e 255 inclusive).
*
* @return valor inteiro até 65535 representados pelos bytes de alta e baixa ordem.
*/
public static int hilo2int(int high, int low) {
return (low | (high << 8));
}
public static byte[] itob(int[] ints) {
byte[] bytes = new byte[ints.length];
for (int i = 0; i < ints.length; i++) bytes[i] = (byte)(ints[i] & 0xff);
return bytes;
}
public static int[] btoi(byte[] bytes) {
int[] ints = new int[bytes.length];
for (int i = 0; i < bytes.length; i++) ints[i] = (int)(bytes[i] & 0xff);
return ints;
}
/**
* Extrai o valor ASCII de um determinado caracter de uma string. Por exemplo:
*
*
* ByteUtils.ascval("ABC", 0); // resulta: 65
* ByteUtils.ascval("ABC", 1); // resulta: 66
* ByteUtils.ascval("ABC", 2); // resulta: 67
*
*
* @param s a string alvo.
*
* @param pos a posição a ser extraído o valor ASCII.
*
* @return o valor ASCII do caracter na posição pos
da string
* s
.
*
* @throws IndexOutOfBoundsException se a posição indicada for menor que zero ou
* maior que o tamanho da string s.length() - 1
.
*/
public static int ascval(String s, int pos) {
return (int)((((byte)(s.charAt(pos))) & 0xff));
}
/**
* Converte uma string contendo uma sequência decimal codificada em BCD
* (Binary-Coded Decimal ?). Esta implementação foi obtida a partir da
* descrição da codificação BCD encontrada no manual de programação das
* impressoras fiscais Bematech® MP-20 FI II.
*
* Se os valores ASCII dos caracteres de uma string forem 0x12, 0x34 e
* 0x56
, então bcd(s, 2)
resultará no valor decimal
* 1234.56
.
*
* @param s a string contendo a sequência BCD.
*
* @param scale o número de casas decimais a serem considerados. Se este
* argumento for menor ou igual a zero, será considerado um valor
* inteiro.
*
* @return um objeto java.math.BigDecimal
contendo o valor
* decimal decodificado.
*
* @throws NumberFormatException se a string s
não representar
* uma sequência BCD válida.
*/
public static BigDecimal bcd(final String s, final int scale) {
StringBuilder hexval = new StringBuilder();
// converte os valores ASCII da string para hexadecimal
for (int i = 0; i < s.length(); i++) {
StringBuilder hex = new StringBuilder(Integer.toString(ascval(s, i), 16));
if (hex.length() != 2) hex.insert(0, "0");
hexval.append(hex);
}
if (scale > 0) {
if (scale > hexval.length()) {
// completa com zeros antes da posição de inserção do ponto decimal
int count = scale - hexval.length();
for (int i = 1; i <= count; i++) hexval.insert(0, "0");
}
// insere um ponto decimal na posição indicada
hexval.insert(hexval.length()-scale, ".");
}
return new BigDecimal(hexval.toString());
}
} // {{{ ByteUtils }}}