@@ 141,6 141,7 @@
border-radius: 4px;
box-shadow: 0 0 100px 0 rgba(0, 0, 0, 0.7);
display: none;
+ overflow: auto;
}
.popover .close {
@@ 157,6 158,12 @@
line-height: 32px;
text-align: center;
}
+
+ .codeblock {
+ background: rgba(0, 0, 0, 0.5);
+ padding: 10px;
+ border-radius: 4px;
+ }
</style>
</head>
<body>
@@ 202,10 209,22 @@
</p>
</div>
+ <div class="popover" id="codegendialog" style="padding: 10px;">
+ <div class="close">×</div>
+ <h2>Unpack</h2>
+ <pre id="cgunpack" class="codeblock"></pre>
+ <h2>Pack</h2>
+ <pre id="cgpack" class="codeblock"></pre>
+ <h2>Documentation</h2>
+ <pre id="cgrst" class="codeblock"></pre>
+ </div>
+
</body>
<script>
const colors = ["#e60049", "#0bb4ff", "#50e991", "#e6d800", "#9b19f5", "#ffa300", "#dc0ab4", "#b3d4ff", "#00bfa0"];
let endianness = '@';
+ let format = null;
+ let rawFormat = '';
function getContrast(hexcolor) {
hexcolor = hexcolor.slice(1);
@@ 218,7 237,7 @@
function onChange() {
- let format = updateFormatTable();
+ format = updateFormatTable();
updateData(format);
}
@@ 231,6 250,12 @@
onChange();
}
+ function doCodegen(event) {
+ event.preventDefault();
+ updateCodegen();
+ document.getElementById('codegendialog').style.display = 'block';
+ }
+
function closeDialog(event) {
event.preventDefault();
let dialogs = document.querySelectorAll('.popover');
@@ 258,6 283,7 @@
document.getElementById('demo').addEventListener('click', doDemo);
document.getElementById('about').addEventListener('click', doAbout);
+ document.getElementById('codegen').addEventListener('click', doCodegen);
document.querySelectorAll('.close').forEach(el => el.addEventListener('click', closeDialog));
});
@@ 390,6 416,7 @@
function updateFormatTable() {
endianness = '@';
+ rawFormat = '';
const table = document.getElementById('table');
const input = document.getElementById('struct');
const value = input.value.replace('struct.pack(', '').replace('struct.unpack(', '').replace(')', '').replace(';', '');
@@ 432,6 459,7 @@
for (let i = 0; i < value.length; i++) {
let c = value[i];
if (c === ' ' || c === '\n') {
+ rawFormat += c;
continue;
}
@@ 452,8 480,10 @@
if (!isNaN(c)) {
number += c;
+ rawFormat += c;
continue;
}
+ rawFormat += c;
switch (c) {
case '@':
@@ 591,6 621,7 @@
}
pos += size * count;
}
+ console.log(rawFormat);
if (parse_vars) {
let vars = value.slice(var_slice + 1);
@@ 641,5 672,70 @@
table.replaceChild(new_tbody, old_tbody);
return result;
}
+
+ function updateCodegen() {
+ const unpackPre = document.getElementById('cgunpack');
+ const packPre = document.getElementById('cgpack');
+ const rstPre = document.getElementById('cgrst');
+
+ let rst = '====== ==== ====== ===========\n' +
+ 'Offset Size Type Description\n' +
+ '====== ==== ====== ===========\n';
+
+ let unpack_short = format.length < 5;
+ let unpack_vars = [];
+ let unpack = '';
+ let pack = '';
+
+ if (!unpack_short) {
+ unpack = 'unpacked = struct.unpack(\'' + rawFormat + '\')\n';
+ }
+
+ const docmap = {
+ 'x': '?',
+ 'c': 'char',
+ 'b': 'i8',
+ 'B': 'u8',
+ '?': 'bool',
+ 'h': 'i16',
+ 'H': 'u16',
+ 'i': 'i32',
+ 'I': 'u32',
+ 'l': 'i32',
+ 'L': 'u32',
+ 'q': 'i64',
+ 'Q': 'u64',
+ 'n': 'i32',
+ 'N': 'u32',
+ 'e': '?',
+ 'f': 'float',
+ 'd': 'double',
+ 's': 'str[]',
+ 'p': 'str[]',
+ 'P': 'void',
+ }
+
+ for (let i = 0; i < format.length; i++) {
+ rst += (format[i]['pos'] + "").padEnd(7);
+ rst += (format[i]['size'] + "").padEnd(5);
+ rst += (docmap[format[i]['format']] + "").padEnd(7);
+ rst += format[i]['var'] + "\n";
+
+ unpack_vars.push(format[i]['var']);
+ if (!unpack_short) {
+ unpack += format[i]['var'] + ' = unpacked[' + i + ']\n';
+ }
+ }
+ rst += '====== ==== ====== ===========\n';
+
+ if (unpack_short) {
+ unpack = unpack_vars.join(', ') + ' = struct.unpack(\'' + rawFormat + '\');';
+ }
+ pack = 'struct.pack(\'' + rawFormat + '\', ' + unpack_vars.join(', ') + ')';
+
+ unpackPre.innerText = unpack;
+ packPre.innerText = pack;
+ rstPre.innerText = rst;
+ }
</script>
</html>