Created
October 4, 2014 19:07
-
-
Save acmi/b2937e2a12e37027ec79 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import javafx.application.Application; | |
import javafx.beans.value.ChangeListener; | |
import javafx.beans.value.ObservableValue; | |
import javafx.geometry.HPos; | |
import javafx.geometry.Insets; | |
import javafx.scene.Scene; | |
import javafx.scene.control.Label; | |
import javafx.scene.control.TextField; | |
import javafx.scene.layout.ColumnConstraints; | |
import javafx.scene.layout.GridPane; | |
import javafx.scene.layout.Priority; | |
import javafx.scene.layout.Region; | |
import javafx.stage.Stage; | |
import java.nio.BufferUnderflowException; | |
import java.nio.ByteBuffer; | |
public class IndexConverter extends Application { | |
@Override | |
public void start(Stage primaryStage) throws Exception { | |
final TextField index = new TextField(); | |
final TextField integer = new TextField(); | |
index.focusedProperty().addListener(new ChangeListener<Boolean>() { | |
ChangeListener<String> indexListener = new ChangeListener<String>() { | |
@Override | |
public void changed(ObservableValue<? extends String> observable, String oldValue, String newValue) { | |
try { | |
byte[] bytes = parseBytes(newValue.replaceAll("\\s", "")); | |
ByteBuffer buffer = ByteBuffer.wrap(bytes); | |
int result = getCompactInt(buffer); | |
if (buffer.position() != buffer.limit()) | |
throw new Exception(); | |
integer.setText(String.valueOf(result)); | |
} catch (Exception e) { | |
integer.setText(""); | |
} | |
} | |
}; | |
@Override | |
public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) { | |
if (newValue) | |
index.textProperty().addListener(indexListener); | |
else | |
index.textProperty().removeListener(indexListener); | |
} | |
}); | |
integer.focusedProperty().addListener(new ChangeListener<Boolean>() { | |
ChangeListener<String> integerListener = new ChangeListener<String>() { | |
@Override | |
public void changed(ObservableValue<? extends String> observable, String oldValue, String newValue) { | |
try { | |
int v = Integer.parseInt(newValue); | |
byte[] bytes = compactIntToByteArray(v); | |
StringBuilder sb = new StringBuilder(String.format("%02X", bytes[0])); | |
for (int i = 1; i < bytes.length; i++) | |
sb.append(String.format(" %02X", bytes[i])); | |
index.setText(sb.toString()); | |
} catch (Exception e) { | |
index.setText(""); | |
} | |
} | |
}; | |
@Override | |
public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) { | |
if (newValue) | |
integer.textProperty().addListener(integerListener); | |
else | |
integer.textProperty().removeListener(integerListener); | |
} | |
}); | |
GridPane pane = new GridPane(); | |
pane.add(new Label("Index"), 0, 0); | |
pane.add(new Label("Integer"), 0, 1); | |
pane.add(index, 1, 0); | |
pane.add(integer, 1, 1); | |
pane.setPadding(new Insets(2., 2., 2., 2.)); | |
pane.setHgap(2.); | |
pane.setVgap(2.); | |
pane.getColumnConstraints().addAll( | |
new ColumnConstraints(Region.USE_PREF_SIZE, Region.USE_COMPUTED_SIZE, Region.USE_PREF_SIZE, Priority.NEVER, HPos.LEFT, true), | |
new ColumnConstraints(0.0, Region.USE_COMPUTED_SIZE, Double.MAX_VALUE, Priority.ALWAYS, HPos.LEFT, true)); | |
primaryStage.setTitle(getClass().getSimpleName()); | |
primaryStage.setScene(new Scene(pane)); | |
primaryStage.show(); | |
} | |
public static byte[] parseBytes(String text) throws NumberFormatException { | |
byte[] bytes = new byte[(text.length() + 1) / 2]; | |
for (int i = bytes.length - 1; i >= 0; i--) { | |
int ind = Math.max(0, text.length() - 2); | |
bytes[i] = (byte) Integer.parseInt(text.substring(ind), 16); | |
text = text.substring(0, ind); | |
} | |
return bytes; | |
} | |
public static int getCompactInt(ByteBuffer input) throws BufferUnderflowException { | |
int output = 0; | |
boolean signed = false; | |
for (int i = 0; i < 5; i++) { | |
int x = input.get() & 0xff; | |
if (i == 0) { | |
if ((x & 0x80) > 0) | |
signed = true; | |
output |= (x & 0x3F); | |
if ((x & 0x40) == 0) | |
break; | |
} else if (i == 4) { | |
output |= (x & 0xF) << (6 + (3 * 7)); | |
} else { | |
output |= (x & 0x7F) << (6 + ((i - 1) * 7)); | |
if ((x & 0x80) == 0) | |
break; | |
} | |
} | |
if (signed) | |
output *= -1; | |
return output; | |
} | |
public static byte[] compactIntToByteArray(int v) { | |
boolean negative = v < 0; | |
v = Math.abs(v); | |
int[] bytes = new int[]{ | |
(v) & 0b00111111, | |
(v >> 6) & 0b01111111, | |
(v >> 6 + 7) & 0b01111111, | |
(v >> 6 + 7 + 7) & 0b01111111, | |
(v >> 6 + 7 + 7 + 7) & 0b01111111 | |
}; | |
if (negative) bytes[0] |= 0b10000000; | |
int size = 5; | |
for (int i = 4; i > 0; i--) { | |
if (bytes[i] != 0) | |
break; | |
size--; | |
} | |
byte[] res = new byte[size]; | |
for (int i = 0; i < size; i++) { | |
if (i != size - 1) | |
bytes[i] |= i == 0 ? 0b01000000 : 0b10000000; | |
res[i] = (byte) bytes[i]; | |
} | |
return res; | |
} | |
public static void main(String[] args) { | |
launch(args); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment