/* * LZ10 quicktool * is really just a quick UI (by voliol) over compressors/decompressors * written for other projects by Nick Kraayenbrink and Aurum respectively, * so they deserve most of the kudos. * The below licence should be compatible with both sources, and is thus * what applies to this code. */ /* * Copyright (C) 2022 voliol * * LZ10 quicktool is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * LZ10 quicktool is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ import java.util.ArrayList; import javafx.application.Application; import javafx.event.ActionEvent; import javafx.event.EventHandler; import javafx.geometry.HPos; import javafx.scene.Scene; import javafx.scene.control.Button; import javafx.scene.control.Label; import javafx.scene.control.TextArea; import javafx.scene.layout.GridPane; import javafx.scene.layout.Pane; import javafx.stage.Stage; public class Main extends Application { private TextArea uncompressedTextArea = new TextArea(); private TextArea compressedTextArea = new TextArea(); private Label feedbackLabel = new Label(); public static void main(String[] args) { launch(); } /* * Returns empty array when the string is non-readable. */ private static byte[] hexToBytes(String s) { ArrayList hexOnly = new ArrayList<>(); for (int i = 0; i < s.length(); i++) { char c = s.charAt(i); if (c >= '0' && c <= '9') { hexOnly.add(c - '0'); } else if (c >= 'A' && c <= 'F') { hexOnly.add(c - 'A' + 10); } else if (c >= 'a' && c <= 'f') { hexOnly.add(c - 'a' + 10); } } if (hexOnly.size() % 2 != 0) { return new byte[0]; } byte[] bytes = new byte[hexOnly.size() / 2]; for (int i = 0; i < hexOnly.size() / 2; i++) { bytes[i] = (byte) ((hexOnly.get(i * 2) << 4) + hexOnly.get(i * 2 + 1)); } return bytes; } /* * Sourced from: * https://stackoverflow.com/questions/9655181/how-to-convert-a-byte-array-to-a- * hex-string-in-java */ private static String bytesToHex(byte[] bytes) { final char[] HEX_ARRAY = "0123456789ABCDEF".toCharArray(); char[] hexChars = new char[bytes.length * 3]; for (int j = 0; j < bytes.length; j++) { int v = bytes[j] & 0xFF; hexChars[j * 3] = HEX_ARRAY[v >>> 4]; hexChars[j * 3 + 1] = HEX_ARRAY[v & 0x0F]; hexChars[j * 3 + 2] = ' '; } return new String(hexChars); } private static byte[] padBytes(byte[] bytes) { final int PAD_AMOUNT = 4; byte[] padded = new byte[bytes.length+PAD_AMOUNT]; for (int i=0; i < bytes.length; i++) { padded[i] = bytes[i]; } return padded; } @Override public void start(Stage primaryStage) throws Exception { Pane mainPane = new Pane(); GridPane grid = setupGrid(); mainPane.getChildren().add(grid); primaryStage.setScene(new Scene(mainPane)); primaryStage.setTitle("LZ10 quicktool"); primaryStage.show(); } private GridPane setupGrid() { GridPane grid = new GridPane(); grid.addRow(0, new Label("Uncompressed:"), new Label("LZ10 Compressed:")); uncompressedTextArea.setWrapText(true); compressedTextArea.setWrapText(true); grid.addRow(1, uncompressedTextArea, compressedTextArea); Button compressButton = new Button("Compress =>"); compressButton.setOnAction(new CompressHandler()); Button uncompressButton = new Button("<= Decompress"); uncompressButton.setOnAction(new DecompressHandler()); grid.addRow(2, compressButton, uncompressButton); grid.add(feedbackLabel, 0, 3, 2, 1); GridPane.setHalignment(feedbackLabel, HPos.CENTER); return grid; } private class CompressHandler implements EventHandler { @Override public void handle(ActionEvent event) { String in = uncompressedTextArea.getText(); byte[] uncompressed = hexToBytes(in); if (uncompressed.length == 0) { feedbackLabel.setText("Error: invalid/no hex values in \"Uncompressed\" text field."); } else { byte[] compressed = DSCmp.compressLZ10(hexToBytes(in)); compressedTextArea.setText(bytesToHex(compressed)); uncompressedTextArea.setText(bytesToHex(uncompressed)); feedbackLabel.setText("Compression successful!"); } } } private class DecompressHandler implements EventHandler { @Override public void handle(ActionEvent event) { String in = compressedTextArea.getText(); byte[] compressed = hexToBytes(in); if (compressed.length == 0) { feedbackLabel.setText("Error: invalid/no hex values in \"Compressed\" text field."); } else { try { // for some reason DSDecmp.Decompress wants some padding at the end of the bytes, this supplies it byte[] padded = padBytes(hexToBytes(in)); byte[] decompressed = DSDecmp.Decompress(padded); String out = bytesToHex(decompressed); uncompressedTextArea.setText(out); feedbackLabel.setText("Uncompression successful!"); } catch (Exception e) { feedbackLabel.setText("Error: could not decompress for unknown reason"); } } } } }