mirror of
https://github.com/WerWolv/ImHex.git
synced 2026-04-03 05:57:40 -05:00
feat: Support for building ImHex for the web (#1328)
Co-authored-by: WerWolv <werwolv98@gmail.com> Co-authored-by: AnnsAnn <git@annsann.eu>
This commit is contained in:
@@ -1133,17 +1133,17 @@ namespace hex::plugin::builtin {
|
||||
}
|
||||
}
|
||||
|
||||
// Tool for converting between different number formats
|
||||
// There are three places where input can be changed; the bit checkboxes, the hex input and the decimal input.
|
||||
// Tool for converting between different number formats.
|
||||
// There are three places where input can be changed; the bit checkboxes, the hex input, and the decimal input.
|
||||
// The bit checkboxes and the hex input are directly related and can be converted between each other easily.
|
||||
// The decimal input is a bit more complicated. IEEE 754 floating point numbers are represented as a sign bit,
|
||||
// an exponent and a mantissa. For details see https://en.wikipedia.org/wiki/IEEE_754.
|
||||
// Workflow is as follows:
|
||||
// From the bit checkboxes determine the integer hex value. This is straightforward.
|
||||
// From the hex value determine the binary floating point value by extracting the sign, exponent and mantissa.
|
||||
// From the binary floating point value determine the decimal floating point value using third party library.
|
||||
// From the hex value determine the binary floating point value by extracting the sign, exponent, and mantissa.
|
||||
// From the binary floating point value determine the decimal floating point value using a third party library.
|
||||
// From the decimal floating point we reconstruct the binary floating point value using internal hardware.
|
||||
// If format is non-standard the reconstruction is done using properties of the format.
|
||||
// If the format is non-standard, the reconstruction is done using properties of the format.
|
||||
void drawIEEE754Decoder() {
|
||||
|
||||
constexpr static auto flags = ImGuiInputTextFlags_EnterReturnsTrue;
|
||||
@@ -1235,16 +1235,16 @@ namespace hex::plugin::builtin {
|
||||
const static auto BitsToFloat = [](IEEE754 &ieee754) {
|
||||
// Zero or denormal
|
||||
if (ieee754.exponentBits == 0) {
|
||||
// result doesn't fit in 128 bits
|
||||
// Result doesn't fit in 128 bits
|
||||
if ((ieee754.exponentBias - 1) > 128)
|
||||
ieee754.exponentValue = std::pow(2.0L, static_cast<long double>(-ieee754.exponentBias + 1));
|
||||
else {
|
||||
if (ieee754.exponentBias == 0) {
|
||||
// exponent is zero
|
||||
// Exponent is zero
|
||||
if (ieee754.mantissaBits == 0)
|
||||
ieee754.exponentValue = 1.0;
|
||||
else
|
||||
// exponent is one
|
||||
// Exponent is one
|
||||
ieee754.exponentValue = 2.0;
|
||||
}
|
||||
else
|
||||
@@ -1253,18 +1253,18 @@ namespace hex::plugin::builtin {
|
||||
}
|
||||
// Normal
|
||||
else {
|
||||
// result doesn't fit in 128 bits
|
||||
// Result doesn't fit in 128 bits
|
||||
if (std::abs(ieee754.exponentBits - ieee754.exponentBias) > 128)
|
||||
ieee754.exponentValue = std::pow(2.0L, static_cast<long double>(ieee754.exponentBits - ieee754.exponentBias));
|
||||
//result fits in 128 bits
|
||||
// Result fits in 128 bits
|
||||
else {
|
||||
// exponent is positive
|
||||
// Exponent is positive
|
||||
if (ieee754.exponentBits > ieee754.exponentBias)
|
||||
ieee754.exponentValue = static_cast<long double>(u128(1) << (ieee754.exponentBits - ieee754.exponentBias));
|
||||
// exponent is negative
|
||||
// Exponent is negative
|
||||
else if (ieee754.exponentBits < ieee754.exponentBias)
|
||||
ieee754.exponentValue = 1.0 / static_cast<long double>(u128(1) << (ieee754.exponentBias - ieee754.exponentBits));
|
||||
// exponent is zero
|
||||
// Exponent is zero
|
||||
else ieee754.exponentValue = 1.0;
|
||||
}
|
||||
}
|
||||
@@ -1275,7 +1275,7 @@ namespace hex::plugin::builtin {
|
||||
|
||||
// Check if all exponent bits are set.
|
||||
if (std::popcount(static_cast<u64>(ieee754.exponentBits)) == static_cast<i64>(ieee754statics.exponentBitCount)) {
|
||||
// if fraction is zero number is infinity.
|
||||
// If fraction is zero number is infinity.
|
||||
if (ieee754.mantissaBits == 0) {
|
||||
if (ieee754.signBits == 0) {
|
||||
|
||||
@@ -1290,7 +1290,7 @@ namespace hex::plugin::builtin {
|
||||
}
|
||||
ieee754.numberType = NumberType::Infinity;
|
||||
|
||||
// otherwise number is NaN.
|
||||
// Otherwise number is NaN.
|
||||
} else {
|
||||
if (ieee754.mantissaBits & (u128(1) << (ieee754statics.mantissaBitCount - 1))) {
|
||||
|
||||
@@ -1305,9 +1305,9 @@ namespace hex::plugin::builtin {
|
||||
}
|
||||
ieee754.numberType = NumberType::NaN;
|
||||
}
|
||||
// if all exponent bits are zero, but we have a non-zero fraction
|
||||
// then the number is denormal which are smaller than regular numbers
|
||||
// but not as precise.
|
||||
// If all exponent bits are zero, but we have a non-zero fraction,
|
||||
// then the number is denormal.
|
||||
// These are smaller than regular numbers but not as precise.
|
||||
} else if (ieee754.exponentBits == 0 && ieee754.mantissaBits != 0) {
|
||||
|
||||
ieee754.numberType = NumberType::Denormal;
|
||||
@@ -1336,7 +1336,7 @@ namespace hex::plugin::builtin {
|
||||
// Sign
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
// this has the effect of dimming the color of the numbers so user doesn't try
|
||||
// This has the effect of dimming the color of the numbers so user doesn't try
|
||||
// to interact with them.
|
||||
ImVec4 textColor = ImGui::GetStyleColorVec4(ImGuiCol_Text);
|
||||
ImGui::BeginDisabled();
|
||||
@@ -1350,7 +1350,7 @@ namespace hex::plugin::builtin {
|
||||
ImGui::Text("+1");
|
||||
ImGui::Unindent(20_scaled);
|
||||
|
||||
//times
|
||||
// Times
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::Text("x");
|
||||
ImGui::TableNextColumn();
|
||||
@@ -1376,7 +1376,7 @@ namespace hex::plugin::builtin {
|
||||
|
||||
ImGui::Unindent(20_scaled);
|
||||
|
||||
//times
|
||||
// Times
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::Text("x");
|
||||
ImGui::TableNextColumn();
|
||||
@@ -1510,22 +1510,21 @@ namespace hex::plugin::builtin {
|
||||
ImGui::Unindent(indent);
|
||||
};
|
||||
|
||||
const static auto FloatToBits = [&specialNumbers](IEEE754 &ieee754, std::string decimalFloatingPointNumberString
|
||||
, std::string_view decimalStrView, std::from_chars_result &res,int totalBitCount) {
|
||||
const static auto FloatToBits = [&specialNumbers](IEEE754 &ieee754, std::string decimalFloatingPointNumberString, int totalBitCount) {
|
||||
|
||||
// Always obtain sign first.
|
||||
if (decimalFloatingPointNumberString[0] == '-') {
|
||||
// and remove it from the string.
|
||||
// And remove it from the string.
|
||||
ieee754.signBits = 1;
|
||||
decimalFloatingPointNumberString.erase(0, 1);
|
||||
} else
|
||||
//important to switch from - to +.
|
||||
// Important to switch from - to +.
|
||||
ieee754.signBits = 0;
|
||||
|
||||
InputType inputType;
|
||||
bool matchFound = false;
|
||||
i32 i;
|
||||
// detect and use special numbers.
|
||||
// Detect and use special numbers.
|
||||
for (i = 0; i < 12; i++) {
|
||||
if (decimalFloatingPointNumberString == specialNumbers[i]) {
|
||||
inputType = InputType(i/3);
|
||||
@@ -1538,10 +1537,9 @@ namespace hex::plugin::builtin {
|
||||
inputType = InputType::regular;
|
||||
|
||||
if (inputType == InputType::regular) {
|
||||
decimalStrView = decimalFloatingPointNumberString;
|
||||
res = std::from_chars(decimalStrView.data(), decimalStrView.data() + decimalStrView.size(), ieee754statics.resultFloat);
|
||||
// this is why we use from_chars
|
||||
if (res.ec != std::errc()) {
|
||||
try {
|
||||
ieee754statics.resultFloat = stod(decimalFloatingPointNumberString);
|
||||
} catch(const std::invalid_argument& _) {
|
||||
inputType = InputType::invalid;
|
||||
}
|
||||
} else if (inputType == InputType::infinity) {
|
||||
@@ -1560,7 +1558,7 @@ namespace hex::plugin::builtin {
|
||||
long double log2Result;
|
||||
|
||||
if (inputType != InputType::invalid) {
|
||||
// deal with zero first so we can use log2.
|
||||
// Deal with zero first so we can use log2.
|
||||
if (ieee754statics.resultFloat == 0.0) {
|
||||
if (ieee754.signBits == 1)
|
||||
ieee754statics.resultFloat = -0.0;
|
||||
@@ -1638,13 +1636,13 @@ namespace hex::plugin::builtin {
|
||||
};
|
||||
|
||||
const static auto ToolMenu = [](i64 &inputFieldWidth) {
|
||||
// we are done. The rest selects the format if user interacts with the widgets.
|
||||
// If precision and exponent match one of the IEEE 754 formats the format is highlighted
|
||||
// and remains highlighted until user changes to a different format. Matching formats occur when
|
||||
// We are done. The rest selects the format if user interacts with the widgets.
|
||||
// If precision and exponent match one of the IEEE 754 formats, the format is highlighted
|
||||
// and remains highlighted until the user changes to a different format. Matching formats occur when
|
||||
// the user clicks on one of the selections or if the slider values match the format in question.
|
||||
// when a new format is selected it may have a smaller number of digits than
|
||||
// When a new format is selected, it may have a smaller number of digits than
|
||||
// the previous selection. Since the largest of the hexadecimal and the decimal
|
||||
// representation widths sets both field widths to the same value we need to
|
||||
// representation widths set both field widths to the same value, we need to
|
||||
// reset it here when a new choice is set.
|
||||
|
||||
auto exponentBitCount = ieee754statics.exponentBitCount;
|
||||
@@ -1705,7 +1703,7 @@ namespace hex::plugin::builtin {
|
||||
|
||||
needsPop = false;
|
||||
if (ImGui::Button("hex.builtin.tools.ieee754.clear"_lang))
|
||||
//this will reset all interactive widgets to zero.
|
||||
// This will reset all interactive widgets to zero.
|
||||
ieee754statics.value = 0;
|
||||
|
||||
ImGui::Separator();
|
||||
@@ -1789,11 +1787,11 @@ namespace hex::plugin::builtin {
|
||||
ieee754.precision = std::ceil(1+(ieee754statics.mantissaBitCount + 1) * std::log10(2.0L));
|
||||
|
||||
// For C++ from_chars is better than strtold.
|
||||
// the main problem is that from_chars will not process special numbers
|
||||
// The main problem is that from_chars will not process special numbers
|
||||
// like inf and nan, so we handle them manually
|
||||
static std::string decimalFloatingPointNumberString;
|
||||
static std::string_view decimalStrView;
|
||||
// use qnan for quiet NaN and snan for signaling NaN
|
||||
|
||||
// Use qnan for quiet NaN and snan for signaling NaN
|
||||
if (ieee754.numberType == NumberType::NaN) {
|
||||
if (ieee754.valueType == ValueType::QuietNaN)
|
||||
decimalFloatingPointNumberString = "qnan";
|
||||
@@ -1809,9 +1807,8 @@ namespace hex::plugin::builtin {
|
||||
|
||||
// We allow any input in order to accept infinities and NaNs, all invalid entries
|
||||
// are detected by from_chars. You can also enter -0 or -inf.
|
||||
std::from_chars_result res;
|
||||
if (ImGui::InputText("##resultFloat", decimalFloatingPointNumberString, flags)) {
|
||||
FloatToBits(ieee754, decimalFloatingPointNumberString, decimalStrView, res, totalBitCount);
|
||||
FloatToBits(ieee754, decimalFloatingPointNumberString, totalBitCount);
|
||||
}
|
||||
ImGui::PopItemWidth();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user