I have the following C-code which I am trying to re-write in java.
I would like to see similar outputs in both of them but I am getting different outputs.
This is for computation of checksum.
Here is the C-code:
#include <ctype.h>
#include <string.h>
#include <stdio.h>
/*~+:CRC Table*/
static unsigned short crctab[256] =
{
0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7,
0x8108, 0x9129, 0xA14A, 0xB16B, 0xC18C, 0xD1AD, 0xE1CE, 0xF1EF,
0x1231, 0x0210, 0x3273, 0x2252, 0x52B5, 0x4294, 0x72F7, 0x62D6,
0x9339, 0x8318, 0xB37B, 0xA35A, 0xD3BD, 0xC39C, 0xF3FF, 0xE3DE,
0x2462, 0x3443, 0x0420, 0x1401, 0x64E6, 0x74C7, 0x44A4, 0x5485,
0xA56A, 0xB54B, 0x8528, 0x9509, 0xE5EE, 0xF5CF, 0xC5AC, 0xD58D,
0x3653, 0x2672, 0x1611, 0x0630, 0x76D7, 0x66F6, 0x5695, 0x46B4,
0xB75B, 0xA77A, 0x9719, 0x8738, 0xF7DF, 0xE7FE, 0xD79D, 0xC7BC,
0x48C4, 0x58E5, 0x6886, 0x78A7, 0x0840, 0x1861, 0x2802, 0x3823,
0xC9CC, 0xD9ED, 0xE98E, 0xF9AF, 0x8948, 0x9969, 0xA90A, 0xB92B,
0x5AF5, 0x4AD4, 0x7AB7, 0x6A96, 0x1A71, 0x0A50, 0x3A33, 0x2A12,
0xDBFD, 0xCBDC, 0xFBBF, 0xEB9E, 0x9B79, 0x8B58, 0xBB3B, 0xAB1A,
0x6CA6, 0x7C87, 0x4CE4, 0x5CC5, 0x2C22, 0x3C03, 0x0C60, 0x1C41,
0xEDAE, 0xFD8F, 0xCDEC, 0xDDCD, 0xAD2A, 0xBD0B, 0x8D68, 0x9D49,
0x7E97, 0x6EB6, 0x5ED5, 0x4EF4, 0x3E13, 0x2E32, 0x1E51, 0x0E70,
0xFF9F, 0xEFBE, 0xDFDD, 0xCFFC, 0xBF1B, 0xAF3A, 0x9F59, 0x8F78,
0x9188, 0x81A9, 0xB1CA, 0xA1EB, 0xD10C, 0xC12D, 0xF14E, 0xE16F,
0x1080, 0x00A1, 0x30C2, 0x20E3, 0x5004, 0x4025, 0x7046, 0x6067,
0x83B9, 0x9398, 0xA3FB, 0xB3DA, 0xC33D, 0xD31C, 0xE37F, 0xF35E,
0x02B1, 0x1290, 0x22F3, 0x32D2, 0x4235, 0x5214, 0x6277, 0x7256,
0xB5EA, 0xA5CB, 0x95A8, 0x8589, 0xF56E, 0xE54F, 0xD52C, 0xC50D,
0x34E2, 0x24C3, 0x14A0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
0xA7DB, 0xB7FA, 0x8799, 0x97B8, 0xE75F, 0xF77E, 0xC71D, 0xD73C,
0x26D3, 0x36F2, 0x0691, 0x16B0, 0x6657, 0x7676, 0x4615, 0x5634,
0xD94C, 0xC96D, 0xF90E, 0xE92F, 0x99C8, 0x89E9, 0xB98A, 0xA9AB,
0x5844, 0x4865, 0x7806, 0x6827, 0x18C0, 0x08E1, 0x3882, 0x28A3,
0xCB7D, 0xDB5C, 0xEB3F, 0xFB1E, 0x8BF9, 0x9BD8, 0xABBB, 0xBB9A,
0x4A75, 0x5A54, 0x6A37, 0x7A16, 0x0AF1, 0x1AD0, 0x2AB3, 0x3A92,
0xFD2E, 0xED0F, 0xDD6C, 0xCD4D, 0xBDAA, 0xAD8B, 0x9DE8, 0x8DC9,
0x7C26, 0x6C07, 0x5C64, 0x4C45, 0x3CA2, 0x2C83, 0x1CE0, 0x0CC1,
0xEF1F, 0xFF3E, 0xCF5D, 0xDF7C, 0xAF9B, 0xBFBA, 0x8FD9, 0x9FF8,
0x6E17, 0x7E36, 0x4E55, 0x5E74, 0x2E93, 0x3EB2, 0x0ED1, 0x1EF0
};
void convert_toASCII (char *buffer, int value)
{
/*
Function converts given 'value' into a 4 byte
ASCII-HEX-String (with leading zeros) to 'buffer[]'
Parameter: char *buffer, int value
Returns: none
*/
static unsigned char hex_num[] = "0123456789ABCDEF";
static unsigned char i; /* HV */
i = (char)((value & 0xf000) >> 12);
*buffer = (char)(hex_num[i]);
++buffer;
i = (char)((value & 0x0f00) >> 8);
*buffer = (char)(hex_num[i]);
++buffer;
i = (char)((value & 0x00f0) >> 4);
*buffer = (char)(hex_num[i]);
++buffer;
i = (char)(value & 0x000f);
*buffer = (char)(hex_num[i]);
}
void calc_crc(unsigned char *databuffer,unsigned int length)
{
/*~+:Modulname: calc_crc */
/*~+:Calculate serial CRC (according CCITT ) */
/*~+:The serial CRC16 is calculated for a certain length (int length) */
/*~+:over bytes in buffer (char databuffer[]) */
/*~+: */
/*~+:Input: *databuffer pointer to data string */
/*~+: laenge number of chars to build CRC for */
/*~+:Output: the CRC will be added in ASCII characters ( 4 chars) */
/*~+: at the end of the given string and terminated with '\0' */
/*~+: The buffer must be able to handle these additional */
/*~+: 5 characters */
static unsigned char tmp;
static unsigned int crc,zaehler;
crc = 0;
for (zaehler = 0;zaehler < length ;zaehler ++)
{
tmp=(unsigned char) (crc>>8) ;
crc=(crc<<8) ^ crctab[tmp] ^ *databuffer;
databuffer++;
}
printf("%u", crc);
/* convert crc -> ASCII */
/* append to string */
convert_toASCII (databuffer, crc);
}
void main(void)
{
static char Data[] = {"abcdefghij"};
static char buffer[64];
strcpy(buffer,Datensatz);
printf("Data : %s \n\r",&buffer[0]);
calc_crc(buffer,10);
printf("CRC : %s \n\r",&buffer[10]);
printf("Data mit CRC: %s \n\r",&buffer[0]);
}
The java code that I have written is:
public final class Checksum
{
public static void main(final String[] args)
{
final String checksumString = "abcdefghij";
final int checksum = calculateCRC16CCITTChecksum(checksumString);
System.out.println("Checksum integer value:" + checksum);
System.out.println("Checksum value in Hex:" + Integer.toHexString(checksum));
}
/**
* #param frame The frame for whose checksum has to be calculated.
* #return The calculated checksum.
*/
private final static int calculateCRC16CCITTChecksum(final String frame)
{
final int[] CRC16_Lookup = {0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7, 0x8108, 0x9129, 0xA14A, 0xB16B, 0xC18C, 0xD1AD, 0xE1CE, 0xF1EF, 0x1231, 0x0210, 0x3273, 0x2252,
0x52B5, 0x4294, 0x72F7, 0x62D6, 0x9339, 0x8318, 0xB37B, 0xA35A, 0xD3BD, 0xC39C, 0xF3FF, 0xE3DE, 0x2462, 0x3443, 0x0420, 0x1401, 0x64E6, 0x74C7, 0x44A4, 0x5485, 0xA56A, 0xB54B, 0x8528,
0x9509, 0xE5EE, 0xF5CF, 0xC5AC, 0xD58D, 0x3653, 0x2672, 0x1611, 0x0630, 0x76D7, 0x66F6, 0x5695, 0x46B4, 0xB75B, 0xA77A, 0x9719, 0x8738, 0xF7DF, 0xE7FE, 0xD79D, 0xC7BC, 0x48C4, 0x58E5,
0x6886, 0x78A7, 0x0840, 0x1861, 0x2802, 0x3823, 0xC9CC, 0xD9ED, 0xE98E, 0xF9AF, 0x8948, 0x9969, 0xA90A, 0xB92B, 0x5AF5, 0x4AD4, 0x7AB7, 0x6A96, 0x1A71, 0x0A50, 0x3A33, 0x2A12, 0xDBFD,
0xCBDC, 0xFBBF, 0xEB9E, 0x9B79, 0x8B58, 0xBB3B, 0xAB1A, 0x6CA6, 0x7C87, 0x4CE4, 0x5CC5, 0x2C22, 0x3C03, 0x0C60, 0x1C41, 0xEDAE, 0xFD8F, 0xCDEC, 0xDDCD, 0xAD2A, 0xBD0B, 0x8D68, 0x9D49,
0x7E97, 0x6EB6, 0x5ED5, 0x4EF4, 0x3E13, 0x2E32, 0x1E51, 0x0E70, 0xFF9F, 0xEFBE, 0xDFDD, 0xCFFC, 0xBF1B, 0xAF3A, 0x9F59, 0x8F78, 0x9188, 0x81A9, 0xB1CA, 0xA1EB, 0xD10C, 0xC12D, 0xF14E,
0xE16F, 0x1080, 0x00A1, 0x30C2, 0x20E3, 0x5004, 0x4025, 0x7046, 0x6067, 0x83B9, 0x9398, 0xA3FB, 0xB3DA, 0xC33D, 0xD31C, 0xE37F, 0xF35E, 0x02B1, 0x1290, 0x22F3, 0x32D2, 0x4235, 0x5214,
0x6277, 0x7256, 0xB5EA, 0xA5CB, 0x95A8, 0x8589, 0xF56E, 0xE54F, 0xD52C, 0xC50D, 0x34E2, 0x24C3, 0x14A0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405, 0xA7DB, 0xB7FA, 0x8799, 0x97B8, 0xE75F,
0xF77E, 0xC71D, 0xD73C, 0x26D3, 0x36F2, 0x0691, 0x16B0, 0x6657, 0x7676, 0x4615, 0x5634, 0xD94C, 0xC96D, 0xF90E, 0xE92F, 0x99C8, 0x89E9, 0xB98A, 0xA9AB, 0x5844, 0x4865, 0x7806, 0x6827,
0x18C0, 0x08E1, 0x3882, 0x28A3, 0xCB7D, 0xDB5C, 0xEB3F, 0xFB1E, 0x8BF9, 0x9BD8, 0xABBB, 0xBB9A, 0x4A75, 0x5A54, 0x6A37, 0x7A16, 0x0AF1, 0x1AD0, 0x2AB3, 0x3A92, 0xFD2E, 0xED0F, 0xDD6C,
0xCD4D, 0xBDAA, 0xAD8B, 0x9DE8, 0x8DC9, 0x7C26, 0x6C07, 0x5C64, 0x4C45, 0x3CA2, 0x2C83, 0x1CE0, 0x0CC1, 0xEF1F, 0xFF3E, 0xCF5D, 0xDF7C, 0xAF9B, 0xBFBA, 0x8FD9, 0x9FF8, 0x6E17, 0x7E36,
0x4E55, 0x5E74, 0x2E93, 0x3EB2, 0x0ED1, 0x1EF0};
// check sum for polynomial 1.x16 + 0.x15 + 0.x14 + 0.x13 + 1.x12 + 0.x11 + 0.x10 + 0.x9 + 0.x8 + 0.x7 + 0.x6 + 1.x5 + 0.x4 + 0.x3 + 0.x2 +0.x1 + 1.x0.
// 1.x16 - implies 1 multiplied by 'x' to the power of 16.
int crc = 0;
for (int i = 0, size = frame.length(); i < size; i++)
{
crc = (crc << 8) ^ CRC16_Lookup[(crc >> 8) & 0xFF] ^ (frame.charAt(i) & 0xFF);
}
return crc & 0xFFFF;
}
}
The integer value output that I get in java code is different from what the decimal value that I get in C, even the hex string conversion in java yields different results to that of hex conversion in C.
Please guide me what I am doing wrong.
Thanks for looking!!
This is not strictly related to an implementation problem, but I guess it's worth mentioning anyway. Keep in mind that some communication protocols require XORing the input values and output values with some value, not to mention bit or byte reflecting of the input data. This happens in Ethernet, which uses CRC-32 for the actual calculations, but the input and output data is XORed with FF..FF (so, it's NOTed), and all the bits in the input byte (or, more naturally, nibble) are reflected. Keep that in mind - the actual calculations might be alright, but there might be something you're simply not aware of in terms of mangling the data, what leads to completely different results.
By code inspection, one can see that in Java the CRC is limited to 16 bits before being printed in decimal (use of & 0xFFFF before returning the function). In C, the value printed is the full unsigned int, so applying the same mask should do the trick.
I can't understand why the hex values differ, though...
Related
This is go code
import (
"C"
"fmt"
)
//export Print
func Print(keys, values [][]byte) {
for len(keys) > 0 {
err := txn.Set(keys[0], values[0])
errMustBeNil(err)
fmt.Printf("%s %s", string(keys[0]), string(values[0]))
keys = keys[1:]
values = values[1:]
}
}
This is libPrint.h
/*
static assertion to make sure the file is being used on architecture
at least with matching size of GoInt.
*/
typedef char _check_for_64_bit_pointer_matching_GoInt[sizeof(void*)==64/8 ? 1:-1];
#ifndef GO_CGO_GOSTRING_TYPEDEF
typedef _GoString_ GoString;
#endif
typedef void *GoMap;
typedef void *GoChan;
typedef struct { void *t; void *v; } GoInterface;
typedef struct { void *data; GoInt len; GoInt cap; } GoSlice;
#endif
/* End of boilerplate cgo prologue. */
#ifdef __cplusplus
extern "C" {
#endif
extern void Print(GoSlice keys, GoSlice values);
#ifdef __cplusplus
}
#endif
This is my Java code,I want to put byte[] into pointer one by one,GoSlice is represents the array[] in go,I don't know if this is correct
public interface Test extends Library {
Test TEST = (Test) Native.load("Print", Test.class);
void Print(GoSlice key, GoSlice val);
class GoSlice extends Structure {
public Pointer[] data;
public long len;
public long cap;
}
static void main(String[] args) {
byte[] byte1 = "key1".getBytes(StandardCharsets.UTF_8);
byte[] byte2 = "value1new".getBytes(StandardCharsets.UTF_8);
GoSlice keys = new GoSlice();
keys.data = new Pointer[1];
keys.data[0] = new Pointer(byte1.length + 1);
keys.len = 1;
keys.cap = 1;
GoSlice values = new GoSlice();
values.data = new Pointer[1];
keys.data[0] = new Pointer(byte2.length + 1);
values.len = 1;
values.cap = 1;
keys.data[0].write(0, byte1, 0, byte1.length);
values.data[0].write(0, byte2, 0, byte2.length);
Test.TEST.Print(keys, values);
}
}
But it doesn't work correctly,I feel that byte[][] is not correctly converted to the type in go.
This is the console log after running the Java program
#
# A fatal error has been detected by the Java Runtime Environment:
#
# SIGSEGV (0xb) at pc=0x00000001a2775a34, pid=64329, tid=0x0000000000002903
#
# JRE version: OpenJDK Runtime Environment (Zulu 8.62.0.19-CA-macos-aarch64) (8.0_332-b09) (build 1.8.0_332-b09)
# Java VM: OpenJDK 64-Bit Server VM (25.332-b09 mixed mode bsd-aarch64 compressed oops)
# Problematic frame:
# C [libsystem_platform.dylib+0x3a34] _platform_memmove+0xf4
#
# Failed to write core dump. Core dumps have been disabled. To enable core dumping, try "ulimit -c unlimited" before starting Java again
#
# An error report file with more information is saved as:
# /Users/user/project/hs_err_pid64329.log
#
# If you would like to submit a bug report, please visit:
# http://www.azul.com/support/
#
This is my first change
public interface TxnClient extends Library {
TxnClient TNX_CLIENT = (TxnClient) Native.load("Tikv", TxnClient.class);
int TxnSave(GoSlice[] key, GoSlice[] val);
class GoSlice extends Structure {
public long cap;
public Pointer data;
public long len;
#Override
protected List<String> getFieldOrder() {
return Arrays.asList("cap", "data", "len");
}
}
static void main(String[] args) {
byte[] key1 = "key1".getBytes(StandardCharsets.UTF_8);
byte[] value1 = "value1new".getBytes(StandardCharsets.UTF_8);
byte[] key2 = "key2".getBytes(StandardCharsets.UTF_8);
byte[] value2 = "value2new".getBytes(StandardCharsets.UTF_8);
GoSlice tmp = new GoSlice();
GoSlice[] keys = (GoSlice[]) tmp.toArray(2);
keys[0].data = new Memory(key1.length + 1);
keys[0].len = keys[0].cap = key1.length;
keys[0].data.write(0, key1, 0, key1.length);
keys[1].data = new Memory(key2.length + 1);
keys[1].len = keys[1].cap = key2.length;
keys[1].data.write(0, key2, 0, key2.length);
GoSlice[] values = (GoSlice[]) tmp.toArray(2);
values[0].data = new Memory(value1.length + 1);
values[0].len = values[0].cap = value1.length;
values[0].data.write(0, value1, 0, value1.length);
values[1].data = new Memory(value2.length + 1);
values[1].len = values[1].cap = value2.length;
values[1].data.write(0, value2, 0, value2.length);
int i = TxnClient.TNX_CLIENT.TxnSave(keys, values);
System.out.println(i);
}
}
5431788016 5431788016panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x2 addr=0x9 pc=0x1225b2b80]
goroutine 17 [running, locked to thread]:
main.TxnSave({0x9, 0x143c281f0, 0x14000182000?}, {0x9, 0x143c281f0, 0x121daf2c8?})
/Users/user/project/print.go:52 +0x180
second change
//export TxnSave
func TxnSave(keys, values [][]byte) (res int) {
// ignore
}
public interface TxnClient extends Library {
TxnClient TNX_CLIENT = (TxnClient) Native.load("Tikv", TxnClient.class);
int TxnSave(GoSlice key, GoSlice val);
class GoSlice extends Structure {
public long cap;
public Pointer data;
public long len;
#Override
protected List<String> getFieldOrder() {
return Arrays.asList("cap", "data", "len");
}
}
static void main(String[] args) {
byte[] key1 = "key1".getBytes(StandardCharsets.UTF_8);
byte[] value1 = "value1new".getBytes(StandardCharsets.UTF_8);
byte[] key2 = "key2".getBytes(StandardCharsets.UTF_8);
byte[] value2 = "value2new".getBytes(StandardCharsets.UTF_8);
GoSlice keys = new GoSlice();
keys.data = new Memory(key1.length + key2.length + 1);
keys.data.write(0, key1, 0, key1.length);
keys.len = keys.cap = key1.length + key2.length;
keys.data.write(key1.length, key2, 0, key2.length);
GoSlice values = new GoSlice();
values.data = new Memory(value1.length + value2.length + 1);
values.len = values.cap = value1.length + value2.length;
values.data.write(0, value1, 0, value1.length);
values.data.write(value1.length, value2, 0, value2.length);
int i = TxnClient.TNX_CLIENT.TxnSave(keys, values);
System.out.println(i);
}
}
[2022/07/31 22:36:57.225 +08:00] [INFO] [client.go:378] ["[pd] create pd client with endpoints"] [pd-address="[127.0.0.1:2379]"]
[2022/07/31 22:36:57.228 +08:00] [INFO] [base_client.go:350] ["[pd] switch leader"] [new-leader=http://127.0.0.1:2379] [old-leader=]
[2022/07/31 22:36:57.228 +08:00] [INFO] [base_client.go:105] ["[pd] init cluster id"] [cluster-id=7126545341327379321]
[2022/07/31 22:36:57.228 +08:00] [INFO] [client.go:673] ["[pd] tso dispatcher created"] [dc-location=global]
4981923696 4981923392panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x2 addr=0x8 pc=0x12b00a6e0]
// this is error
goroutine 17 [running, locked to thread]:
main.TxnSave({0x8, 0x128f21f70, 0x14000190000?}, {0x12, 0x128f21e40, 0x12a806d38?})
/Users/user/go-tikv/tikv.go:53 +0x180
You're misunderstanding the Pointer constructor's argument. It's a native peer value, not an allocation size.
What you have:
keys.data[0] = new Pointer(byte1.length + 1);
From the Pointer Javadoc:
public Pointer(long peer)
Create from native pointer. Don't use this unless you know what you're doing.
The correct way to allocate new memory (which calls malloc() internally) is the Memory class which extends Pointer. The argument for the Memory constructor is indeed the size:
public Memory(long size)
Allocate space in the native heap via a call to C's malloc.
Parameters:
size - number of bytes of space to allocate
So you want:
keys.data[0] = new Memory(byte1.length + 1);
One other note:
Memory isn't cleared on allocation, so if you want that "+1" null terminator you need to either clear() the memory or explicitly set that null byte when writing a string to it (or perhaps append a null byte to the string in Java before converting to bytes).
Updating for your follow-on questions:
You have a mismatch between the C header (which has data first followed by len and cap and your own GoSlice structure definition which puts data in the middle. When you pass this to native, you are just sending the value of that initial long which is probably zero, and getting the nil pointer error.
Additionally, you are not allocating enough memory for what you're doing. When you declare a Structure in JNA it allocates the memory it needs. In your earlier version of code you used Structure.toArray() to allocate more memory for more structures -- this was correct (but you did it twice!). You should do that once.
In your latest code you set value as just one GoSlice structure. That memory is just 24 bytes, for the two longs and the Pointer. But then for your second array value you are using the original data (which is in the wrong order) and trying to write to a memory location that isn't even allocated.
In summary:
Declare the field order in your Java GoSlice to match the native header
Use the Structure's toArray() on an initial GoSlice structure to allocate space for an array of them.
Use the data field of the GoSlice[n] structure to write the string values to.
hello I am trying to use this code to ultimately be able to add a file into it so it reads the file and runs through this crc16 but I keep getting this error
"Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 0
at Main.main(Main.java:51)
"
public class Main
{
public static void main(String[] args)
{
int[] table =
{
0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241,
0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 0xC481, 0x0440,
0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40,
0x0A00, 0xCAC1, 0xCB81, 0x0B40, 0xC901, 0x09C0, 0x0880, 0xC841,
0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40,
0x1E00, 0xDEC1, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41,
0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641,
0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040,
0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, 0xF281, 0x3240,
0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441,
0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, 0x3E80, 0xFE41,
0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840,
0x2800, 0xE8C1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41,
0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40,
0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640,
0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, 0x2080, 0xE041,
0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240,
0x6600, 0xA6C1, 0xA781, 0x6740, 0xA501, 0x65C0, 0x6480, 0xA441,
0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41,
0xAA01, 0x6AC0, 0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881, 0x6840,
0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41,
0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40,
0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1, 0xB681, 0x7640,
0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041,
0x5000, 0x90C1, 0x9181, 0x5140, 0x9301, 0x53C0, 0x5280, 0x9241,
0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481, 0x5440,
0x9C01, 0x5CC0, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40,
0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880, 0x9841,
0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40,
0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80, 0x8C41,
0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641,
0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040,
};
byte[] bytes = args[0].getBytes();
int crc = 0x0000;
for (byte b : bytes)
{
crc = (crc >>> 8) ^ table[(crc ^ b) & 0xff];
}
System.out.println("CRC16 = " + Integer.toHexString(crc));
}
}
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
Hi I have this C crc16 implementation:
const unsigned short CRCtbl[ 256 ] =
{
0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241,
0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 0xC481, 0x0440,
0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40,
0x0A00, 0xCAC1, 0xCB81, 0x0B40, 0xC901, 0x09C0, 0x0880, 0xC841,
0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40,
0x1E00, 0xDEC1, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41,
0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641,
0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040,
0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, 0xF281, 0x3240,
0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441,
0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, 0x3E80, 0xFE41,
0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840,
0x2800, 0xE8C1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41,
0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40,
0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640,
0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, 0x2080, 0xE041,
0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240,
0x6600, 0xA6C1, 0xA781, 0x6740, 0xA501, 0x65C0, 0x6480, 0xA441,
0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41,
0xAA01, 0x6AC0, 0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881, 0x6840,
0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41,
0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40,
0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1, 0xB681, 0x7640,
0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041,
0x5000, 0x90C1, 0x9181, 0x5140, 0x9301, 0x53C0, 0x5280, 0x9241,
0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481, 0x5440,
0x9C01, 0x5CC0, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40,
0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880, 0x9841,
0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40,
0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80, 0x8C41,
0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641,
0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081,
0x4040
};
unsigned short Crc_16(unsigned char *str, int n)
{
unsigned short crc = 0xFFFF;
do
{
crc = ( crc >> 8 ) ^ CRCtbl[ ( crc & 0xFF ) ^ *str ];
str++;
}
while(--n);
return(crc);
}
I need to convert it into java one. My problem is that,since java does not provide unsigned int type, the implementation fails in some cases (some info[] byte >127 when considering it as unsigned).
private int crc_xor(byte[] info) {
int[] table = {
0x0000 ,0xC0C1 ,0xC181 ,0x0140 ,0xC301 ,0x03C0 ,0x0280 ,0xC241,
0xC601 ,0x06C0 ,0x0780 ,0xC741 ,0x0500 ,0xC5C1 ,0xC481 ,0x0440,
0xCC01 ,0x0CC0 ,0x0D80 ,0xCD41 ,0x0F00 ,0xCFC1 ,0xCE81 ,0x0E40,
0x0A00 ,0xCAC1 ,0xCB81 ,0x0B40 ,0xC901 ,0x09C0 ,0x0880 ,0xC841,
0xD801 ,0x18C0 ,0x1980 ,0xD941 ,0x1B00 ,0xDBC1 ,0xDA81 ,0x1A40,
0x1E00 ,0xDEC1 ,0xDF81 ,0x1F40 ,0xDD01 ,0x1DC0 ,0x1C80 ,0xDC41,
0x1400 ,0xD4C1 ,0xD581 ,0x1540 ,0xD701 ,0x17C0 ,0x1680 ,0xD641,
0xD201 ,0x12C0 ,0x1380 ,0xD341 ,0x1100 ,0xD1C1 ,0xD081 ,0x1040,
0xF001 ,0x30C0 ,0x3180 ,0xF141 ,0x3300 ,0xF3C1 ,0xF281 ,0x3240,
0x3600 ,0xF6C1 ,0xF781 ,0x3740 ,0xF501 ,0x35C0 ,0x3480 ,0xF441,
0x3C00 ,0xFCC1 ,0xFD81 ,0x3D40 ,0xFF01 ,0x3FC0 ,0x3E80 ,0xFE41,
0xFA01 ,0x3AC0 ,0x3B80 ,0xFB41 ,0x3900 ,0xF9C1 ,0xF881 ,0x3840,
0x2800 ,0xE8C1 ,0xE981 ,0x2940 ,0xEB01 ,0x2BC0 ,0x2A80 ,0xEA41,
0xEE01 ,0x2EC0 ,0x2F80 ,0xEF41 ,0x2D00 ,0xEDC1 ,0xEC81 ,0x2C40,
0xE401 ,0x24C0 ,0x2580 ,0xE541 ,0x2700 ,0xE7C1 ,0xE681 ,0x2640,
0x2200 ,0xE2C1 ,0xE381 ,0x2340 ,0xE101 ,0x21C0 ,0x2080 ,0xE041,
0xA001 ,0x60C0 ,0x6180 ,0xA141 ,0x6300 ,0xA3C1 ,0xA281 ,0x6240,
0x6600 ,0xA6C1 ,0xA781 ,0x6740 ,0xA501 ,0x65C0 ,0x6480 ,0xA441,
0x6C00 ,0xACC1 ,0xAD81 ,0x6D40 ,0xAF01 ,0x6FC0 ,0x6E80 ,0xAE41,
0xAA01 ,0x6AC0 ,0x6B80 ,0xAB41 ,0x6900 ,0xA9C1 ,0xA881 ,0x6840,
0x7800 ,0xB8C1 ,0xB981 ,0x7940 ,0xBB01 ,0x7BC0 ,0x7A80 ,0xBA41,
0xBE01 ,0x7EC0 ,0x7F80 ,0xBF41 ,0x7D00 ,0xBDC1 ,0xBC81 ,0x7C40,
0xB401 ,0x74C0 ,0x7580 ,0xB541 ,0x7700 ,0xB7C1 ,0xB681 ,0x7640,
0x7200 ,0xB2C1 ,0xB381 ,0x7340 ,0xB101 ,0x71C0 ,0x7080 ,0xB041,
0x5000 ,0x90C1 ,0x9181 ,0x5140 ,0x9301 ,0x53C0 ,0x5280 ,0x9241,
0x9601 ,0x56C0 ,0x5780 ,0x9741 ,0x5500 ,0x95C1 ,0x9481 ,0x5440,
0x9C01 ,0x5CC0 ,0x5D80 ,0x9D41 ,0x5F00 ,0x9FC1 ,0x9E81 ,0x5E40,
0x5A00 ,0x9AC1 ,0x9B81 ,0x5B40 ,0x9901 ,0x59C0 ,0x5880 ,0x9841,
0x8801 ,0x48C0 ,0x4980 ,0x8941 ,0x4B00 ,0x8BC1 ,0x8A81 ,0x4A40,
0x4E00 ,0x8EC1 ,0x8F81 ,0x4F40 ,0x8D01 ,0x4DC0 ,0x4C80 ,0x8C41,
0x4400 ,0x84C1 ,0x8581 ,0x4540 ,0x8701 ,0x47C0 ,0x4680 ,0x8641,
0x8201 ,0x42C0 ,0x4380 ,0x8341 ,0x4100 ,0x81C1 ,0x8081 ,0x4040};
int crc16=0;
int pos=0;
int lungh=info.length;
lungh-=1;
while(lungh>=0)
{
crc16 = ((crc16 >> 8) ^ table[(crc16&0xFF) ^ info[pos]]) & 0xFFFF;
pos+=1;
lungh-=1;
}
return crc16;
}
There are many java crc16 implementations but not this (used in SIA standard).
Can you help me?
thanks
Try changing the (crc16&0xFF) ^ info[pos] to (crc16 ^ info[pos])&0xFF.
So I found this code at http://introcs.cs.princeton.edu/java/51data/CRC16.java.html
public class CRC16 {
public static void main(String[] args) {
int[] table = {
0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241,
0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 0xC481, 0x0440,
0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40,
0x0A00, 0xCAC1, 0xCB81, 0x0B40, 0xC901, 0x09C0, 0x0880, 0xC841,
0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40,
0x1E00, 0xDEC1, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41,
0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641,
0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040,
0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, 0xF281, 0x3240,
0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441,
0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, 0x3E80, 0xFE41,
0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840,
0x2800, 0xE8C1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41,
0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40,
0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640,
0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, 0x2080, 0xE041,
0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240,
0x6600, 0xA6C1, 0xA781, 0x6740, 0xA501, 0x65C0, 0x6480, 0xA441,
0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41,
0xAA01, 0x6AC0, 0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881, 0x6840,
0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41,
0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40,
0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1, 0xB681, 0x7640,
0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041,
0x5000, 0x90C1, 0x9181, 0x5140, 0x9301, 0x53C0, 0x5280, 0x9241,
0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481, 0x5440,
0x9C01, 0x5CC0, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40,
0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880, 0x9841,
0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40,
0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80, 0x8C41,
0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641,
0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040,
};
byte[] bytes = args[0].getBytes();
int crc = 0x0000;
for (byte b : bytes) {
crc = (crc >>> 8) ^ table[(crc ^ b) & 0xff];
}
System.out.println("CRC16 = " + Integer.toHexString(crc));
}
}
Anyway everything works fine when I run in a cmd line: java -jar CRC16.jar 123456789
But I can't figure out how to set the arg (123456789) as a variable in the code so I don't have to type anything in when I run the jar file.
This is your class complete with the hardcoded number:
public static void main(String[] args) {
int[] table = {
0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241,
0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 0xC481, 0x0440,
0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40,
0x0A00, 0xCAC1, 0xCB81, 0x0B40, 0xC901, 0x09C0, 0x0880, 0xC841,
0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40,
0x1E00, 0xDEC1, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41,
0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641,
0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040,
0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, 0xF281, 0x3240,
0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441,
0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, 0x3E80, 0xFE41,
0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840,
0x2800, 0xE8C1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41,
0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40,
0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640,
0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, 0x2080, 0xE041,
0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240,
0x6600, 0xA6C1, 0xA781, 0x6740, 0xA501, 0x65C0, 0x6480, 0xA441,
0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41,
0xAA01, 0x6AC0, 0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881, 0x6840,
0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41,
0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40,
0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1, 0xB681, 0x7640,
0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041,
0x5000, 0x90C1, 0x9181, 0x5140, 0x9301, 0x53C0, 0x5280, 0x9241,
0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481, 0x5440,
0x9C01, 0x5CC0, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40,
0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880, 0x9841,
0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40,
0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80, 0x8C41,
0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641,
0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040,
};
String stringa = "123456789";
byte[] bytes = stringa.getBytes();
int crc = 0x0000;
for (byte b : bytes) {
crc = (crc >>> 8) ^ table[(crc ^ b) & 0xff];
}
System.out.println("CRC16 = " + Integer.toHexString(crc));
}
I do sometimes:
public static void main(String[] args) {
if (args.length == 0) {
args = new String[] {"123456789"};
}
Actually implementing default arguments, when none are given. In your IDE one also may often set default run arguments.
My project at work is using the Jackson JSON serializer to convert a bunch of Java objects into Strings in order to send them to REST services.
Some of these objects contain sensitive data, so I've written custom serializers to serialize these objects to JSON strings, then gzip them, then encrypt them using AES;
This turns the strings into byte arrays, so I use the Base64 encoder in Apache commons codec to convert the byte arrays into strings. The custom deserializers behind the REST interfaces reverse this process:
base64 decode -> decrypt -> decompress -> deserialize using default Jackson deserializer.
Base64 encoding increases the size of the output (the gzip step in serialization is meant to help ameliorate this increase), so I checked Google to see if there was a more efficient alternative, which led me to this previous stackoverflow thread that brought up Ascii85 encoding as a more efficient alternative -
Base64 adds 33% to the size of the output, Ascii85 adds 25% to the size of the output.
I found a few Java Ascii85 implementations e.g. Apache pdfbox, but I'm a bit leery to use the encoding - it seems like hardly anybody is using or implementing it, which might just mean that Base64 has more inertia, or which may instead mean that there's some wonky problem with Ascii85.
Does anybody know more on this subject? Are there any problems with Ascii85 that mean that I should use Base64 instead?
Base64 is way more common. The difference in size really isn't that significant in most cases, and if you add at the HTTP level (which will compress the base64) instead of within your payload, you may well find the difference goes away entirely.
Are there any problems with Ascii85 that mean that I should use Base64 instead?
I would strongly advise using base64 just because it's so much more widespread. It's pretty much the canonical way of representing binary data as text (unless you want to use hex, of course).
ASCII85 is a nice encoding to use to save that extra bit of space. But it outputs many characters that would need to be escaped if naively sent over HTTP. Base64 encoding has a variant that can be sent over HTTP without any escaping.
Here's a javascript ASCII85 encoder in case anyone needs to try:
// By Steve Hanov. Released to the public domain.
function encodeAscii85(input) {
var output = "<~";
var chr1, chr2, chr3, chr4, chr, enc1, enc2, enc3, enc4, enc5;
var i = 0;
while (i < input.length) {
// Access past the end of the string is intentional.
chr1 = input.charCodeAt(i++);
chr2 = input.charCodeAt(i++);
chr3 = input.charCodeAt(i++);
chr4 = input.charCodeAt(i++);
chr = ((chr1 << 24) | (chr2 << 16) | (chr3 << 8) | chr4) >>> 0;
enc1 = (chr / (85 * 85 * 85 * 85) | 0) % 85 + 33;
enc2 = (chr / (85 * 85 * 85) | 0) % 85 + 33;
enc3 = (chr / (85 * 85) | 0 ) % 85 + 33;
enc4 = (chr / 85 | 0) % 85 + 33;
enc5 = chr % 85 + 33;
output += String.fromCharCode(enc1) +
String.fromCharCode(enc2);
if (!isNaN(chr2)) {
output += String.fromCharCode(enc3);
if (!isNaN(chr3)) {
output += String.fromCharCode(enc4);
if (!isNaN(chr4)) {
output += String.fromCharCode(enc5);
}
}
}
}
output += "~>";
return output;
}
<input onKeyUp="result.innerHTML = encodeAscii85(this.value)" placeholder="write text here" type="text">
<p id="result"></p>
Here is matching ASCII85 AKA Base85 decoder (for user Qwerty) in JavaScript:
function decode_ascii85(a) {
var c, d, e, f, g, h = String, l = "length", w = 255, x = "charCodeAt", y = "slice", z = "replace";
for ("<~" === a[y](0, 2) && "~>" === a[y](-2), a = a[y](2, -2)[z](/\s/g, "")[z]("z", "!!!!!"),
c = "uuuuu"[y](a[l] % 5 || 5), a += c, e = [], f = 0, g = a[l]; g > f; f += 5) d = 52200625 * (a[x](f) - 33) + 614125 * (a[x](f + 1) - 33) + 7225 * (a[x](f + 2) - 33) + 85 * (a[x](f + 3) - 33) + (a[x](f + 4) - 33),
e.push(w & d >> 24, w & d >> 16, w & d >> 8, w & d);
return function(a, b) {
for (var c = b; c > 0; c--) a.pop();
}(e, c[l]), h.fromCharCode.apply(h, e);
}
<input onKeyUp="result.innerHTML = decode_ascii85(this.value)" placeholder="insert encoded string here" type="text">
<p id="result"></p>
example: <xmp><~<+oue+DGm>#3BW*D/a<&+EV19F<L~></xmp>