ASCII art diagram converter: Difference between revisions
m
→{{header|Wren}}: Minor tidy
m (→Parsing: edited header) |
m (→{{header|Wren}}: Minor tidy) |
||
(6 intermediate revisions by 5 users not shown) | |||
Line 47:
=={{header|AArch64 Assembly}}==
{{works with|as|Raspberry Pi 3B version Buster 64 bits <br> or android 64 bits with application Termux }}
<syntaxhighlight lang="aarch64 assembly">
/* ARM assembly AARCH64 Raspberry PI 3B or android 64 bits */
/* program asciiDiagram64.s */
Line 506:
/* for this file see task include a file in language AArch64 assembly */
.include "../includeARM64.inc"
</syntaxhighlight>
{{output}}
<pre>
Line 557:
=={{header|ARM Assembly}}==
{{works with|as|Raspberry Pi <br> or android 32 bits with application Termux}}
<syntaxhighlight lang="arm assembly">
/* ARM assembly Raspberry PI or android 32 bits */
/* program asciiDiagram.s */
Line 964:
/***************************************************/
.include "../affichage.inc"
</syntaxhighlight>
{{Output}}
<pre>
Line 1,013:
Name ARCOUNT value : 0110100110100100
</pre>
=={{header|AutoHotkey}}==
<syntaxhighlight lang="AutoHotkey">Header := "
(LTrim
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| ID |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|QR| Opcode |AA|TC|RD|RA| Z | RCODE |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| QDCOUNT |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| ANCOUNT |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| NSCOUNT |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| ARCOUNT |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
)"
Data := "78477BBF5496E12E1BF169A4"
MsgBox % result := ASCII_art_diagram_converter(Header, Data)
return
ASCII_art_diagram_converter(Header, Data){
oDataBin := []
for i, h in StrSplit(Data)
for i, v in StrSplit(SubStr("0000" . ConvertBase(16, 2, h), -3))
oDataBin.Push(v)
bitWidth := StrLen(StrSplit(Header, "+").2) + 1
prevW := 0
result := "Name`t`tSize`tBinary"
for i, line in StrSplit(Header, "`n", "`r")
{
if Mod(A_Index, 2)
continue
strtPos := 0
loop
{
if w := (strtPos := InStr(line, "|",, ++strtPos)) // bitWidth
{
b := ""
loop % width := w - prevW
b .= oDataBin.RemoveAt(1)
result .= "`n" Trim(StrSplit(line, "|")[A_Index]) "`t`t" width . "`t" b
}
prevW := w
}
until !strtPos
}
return result
}
ConvertBase(InputBase, OutputBase, nptr){ ; Base 2 - 36 ; https://www.autohotkey.com/boards/viewtopic.php?t=3925#p21143
static u := A_IsUnicode ? "_wcstoui64" : "_strtoui64"
static v := A_IsUnicode ? "_i64tow" : "_i64toa"
VarSetCapacity(s, 66, 0)
value := DllCall("msvcrt.dll\" u, "Str", nptr, "UInt", 0, "UInt", InputBase, "CDECL Int64")
DllCall("msvcrt.dll\" v, "Int64", value, "Str", s, "UInt", OutputBase, "CDECL")
return s
}</syntaxhighlight>
{{out}}
<pre>Name Size Binary
ID 16 0111100001000111
QR 1 0
Opcode 4 1111
AA 1 0
TC 1 1
RD 1 1
RA 1 1
Z 3 011
RCODE 4 1111
QDCOUNT 16 0101010010010110
ANCOUNT 16 1110000100101110
NSCOUNT 16 0001101111110001
ARCOUNT 16 0110100110100100</pre>
=={{header|C}}==
interpret text diagram as data structure
<syntaxhighlight lang="c">
#include <stdlib.h>
#include <stdio.h>
Line 1,139 ⟶ 1,216:
header[BITS] = 0xB50A;
}
</syntaxhighlight>
{{out}}
<pre>
Line 1,166 ⟶ 1,243:
The ASCII diagram is parsed at compile time into a data structure that is used at runtime to encode and decode the fields.
<
#include <bitset>
#include <iostream>
Line 1,325 ⟶ 1,402:
cout << "Decoded raw data:\n";
Decode<art>(rawData);
}</
{{out}}
<pre>
Line 1,350 ⟶ 1,427:
An invalid table will cause a compilation error - here the ANCOUNT field is missing.
<
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| ID |
Line 1,364 ⟶ 1,441:
| ARCOUNT |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+)";
</syntaxhighlight>
GCC 11 gives this error
Line 1,380 ⟶ 1,457:
=={{header|D}}==
This solution generates anonymous struct code at compile-time, that can be mixed-in inside a struct or class.
<
import std.conv: text;
import std.format: format;
Line 1,580 ⟶ 1,657:
assert(h.ARCOUNT == 255);
assert(h.Opcode == 7);
}</
{{out}}
<pre>[0, 10, 56, 128, 0, 0, 0, 0, 0, 0, 0, 255]</pre>
Line 1,594 ⟶ 1,671:
=={{header|Go}}==
<
import (
Line 1,721 ⟶ 1,798:
hex := "78477bbf5496e12e1bf169a4" // test string
unpack(results, hex)
}</
{{out}}
Line 1,787 ⟶ 1,864:
===Variant based on parsing===
<
import Control.Monad (guard)
Line 1,860 ⟶ 1,937:
["011110000100011101111011101111110101010010010110",
"111000010010111000011011111100010110100110100100"]
</syntaxhighlight>
<pre>λ> let d = read diagram :: Data Int
Line 1,917 ⟶ 1,994:
===List-based interpretation with validation===
<
import Data.List.Split (splitOn)
import Control.Monad (unless)
Line 1,926 ⟶ 2,003:
process d = do
let l = length (head d)
unless (all ((l ==) . length) d) $ Left "Table is not aligned!"
w <- readHLine (head d)
let rows = filter ((/= "+-") . nub) d
Line 1,934 ⟶ 2,010:
readHLine s = do
let cols = splitOn "--" s
unless (nub cols == ["+"]) $ Left ("Invalid header: " ++ s)
return $ length cols - 1
readField s = do
let n = length s + 1
unless (n `mod` 3 == 0) $ Left ("Field is not aligned: " ++ s)
return $ Field (filter (/= ' ') s) (n `div` 3) Nothing
Line 1,947 ⟶ 2,021:
let fields = filter (not.null) $ splitOn "|" s
row <- traverse readField fields
unless (sum (fieldSize <$> row) == n) $ Left $ "Fields are not aligned at row\n " ++ s
return row</syntaxhighlight>
=={{header|J}}==
<
soul=: -. {.
Line 1,986 ⟶ 2,059:
starter=:1 :0
0"0 labels normalize m
)</
Sample definition (note the deliberate introduction of extraneous whitespace in locations the task requires us to ignore it.
<
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| ID |
Line 2,011 ⟶ 2,084:
get=: sample getter
set=: sample setter
start=: sample starter</
Example data for sample definition:
<syntaxhighlight lang="j">
4095 13 5 6144 4096 'ID Opcode RCODE ARCOUNT QDCOUNT' set start
4095 0 13 0 0 0 0 0 5 4096 0 0 6144
Line 2,023 ⟶ 2,096:
10 0 7 0 0 0 1 0 0 0 0 0 255
'Opcode' get unpack 0 10 56 128 0 0 0 0 0 0 0 255
7</
In other words:
Line 2,039 ⟶ 2,112:
Separate methods to validate, display, decode ASCII art, and decode hex value.
<syntaxhighlight lang="java">
import java.math.BigInteger;
import java.util.ArrayList;
Line 2,194 ⟶ 2,267:
}
</syntaxhighlight>
{{out}}
<pre>
Line 2,256 ⟶ 2,329:
=={{header|JavaScript}}==
<
const trimWhitespace = s => s.trim();
const isNotEmpty = s => s !== '';
Line 2,356 ⟶ 2,429:
const parser = parseDiagram(dia);
parser('78477bbf5496e12e1bf169a4');</
{{out}}
<pre>
Line 2,416 ⟶ 2,489:
=={{header|Julia}}==
The validator() function can be customized. The one used only checks length.
<
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| ID |
Line 2,482 ⟶ 2,555:
bitreader(decoded, testhexdata)
</
<pre>
Diagram as bit fields:
Line 2,521 ⟶ 2,594:
=={{header|Lua}}==
Provided mainly to illustrate the string-parsing aspect, not necessarily the bit-structure aspect...
<
local lines = {}
for s in diagram:gmatch("[^\r\n]+") do
Line 2,570 ⟶ 2,643:
local item = schema[i]
print(string.format("%-8s %8d %8d", item.name, item.numbits, item.offset))
end</
{{out}}
<pre>NAME NUMBITS OFFSET
Line 2,603 ⟶ 2,676:
Of course, the second mechanism may be used for all cases. The first mechanism is mainly interesting to show how it is possible, using Nim powerful macro system, to create a type ''ex nihilo''.
<
import strutils
import tables
Line 3,097 ⟶ 3,170:
# Hexadecimal representation.
echo "Hexadecimal representation: ", header2.toHex()</
{{out}}
Line 3,141 ⟶ 3,214:
=={{header|Ol}}==
<
(import (owl parse))
Line 3,205 ⟶ 3,278:
(print (car x) " == " (cdr x) " (" (number->string (cdr x) 2) ")"))
datastructure)
</syntaxhighlight>
{{out}}
<pre>$ ol ascii_art_diagram_converter.scm
Line 3,242 ⟶ 3,315:
=={{header|Perl}}==
<
use strict;
Line 3,280 ⟶ 3,353:
print "\ntemplate = $template\n\n";
use Data::Dump 'dd'; dd 'datastructure', \%datastructure;</
{{out}}
<pre>
Line 3,321 ⟶ 3,394:
=={{header|Phix}}==
Should work on any width, but didn't actually test, or verify width is 8/16/32/64.
<!--<
<span style="color: #008080;">function</span> <span style="color: #000000;">interpret</span><span style="color: #0000FF;">(</span><span style="color: #004080;">sequence</span> <span style="color: #000000;">lines</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">if</span> <span style="color: #7060A8;">remainder</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">lines</span><span style="color: #0000FF;">),</span><span style="color: #000000;">2</span><span style="color: #0000FF;">)!=</span><span style="color: #000000;">1</span> <span style="color: #008080;">then</span>
Line 3,425 ⟶ 3,498:
<span style="color: #000000;">unpack</span><span style="color: #0000FF;">(</span>x"<span style="color: #0000FF;">78477bbf5496e12e1bf169a4</span>"<span style="color: #0000FF;">,</span><span style="color: #000000;">res</span><span style="color: #0000FF;">)</span>
<!--</
{{out}}
<pre>
Line 3,465 ⟶ 3,538:
=={{header|Python}}==
<
"""
http://rosettacode.org/wiki/ASCII_art_diagram_converter
Line 3,620 ⟶ 3,693:
unpack(results, hex)
</syntaxhighlight>
{{out}}
Line 3,694 ⟶ 3,767:
<b><code>ascii-art-parser.rkt</code></b>
Note that this is in the <code>racket/base</code> language so it doesn't overburden the modules that import it, especially since they're at the suntax phase.
<
(require (only-in racket/list drop-right)
(only-in racket/string string-trim))
Line 3,752 ⟶ 3,825:
(define cell-end-bit (hash-ref pos->bit-end# (cdr cp)))
(list word cell-start-bit cell-end-bit (string->symbol (string-trim (substring cnt 1))))))))
(values fields bits/word))</
<b><code>ascii-art-reader.rkt</code></b>
<
(require (for-syntax "ascii-art-parser.rkt"))
(require (for-syntax racket/syntax))
Line 3,822 ⟶ 3,895:
(define rv (make-bytes (* word-size #,(quotient bits/word 8))))
set-fields-bits
rv))))]))</
<b><code>test-ascii-art-reader.rkt</code></b>
<
(require "ascii-art-reader.rkt")
(require "ascii-art-parser.rkt")
Line 3,927 ⟶ 4,000:
(test
(rfc-1035-header-Z (bytes->rfc-1035-header (rfc-1035-header->bytes h))) => 7
(rfc-1035-header-RA (bytes->rfc-1035-header (rfc-1035-header->bytes h))) => 0)</
{{out}}
Line 3,936 ⟶ 4,009:
{{works with|Rakudo|2018.05}}
<syntaxhighlight lang="raku"
rule TOP { <.line-separator> [<line> <.line-separator>]+ }
rule line-separator { <.ws> '+--'+ '+' }
Line 3,992 ⟶ 4,065:
say "\nAnd unpack it";
printf("%7s, %02d bits: %s\n", %structure<fields>[$_]<ID>, %structure<fields>[$_]<bits>,
deconstruct($bitstr, %structure)[$_]) for ^@(%structure<fields>);</
{{out}}
<pre>Line width: 16 bits
Line 4,032 ⟶ 4,105:
=={{header|REXX}}==
Some code was added to the REXX program to validate the input file.
<
numeric digits 100 /*be able to handle large numbers. */
er= '***error*** illegal input txt' /*a literal used for error messages. */
Line 4,085 ⟶ 4,158:
exit 0 /*stick a fork in it, we're all done. */
/*──────────────────────────────────────────────────────────────────────────────────────*/
lower: l= 'abcdefghijklmnopqrstuvwxyz'; u=l; upper u; return translate( arg(1), l, u)</
{{out|output|text= when using the default input:}}
<pre>
Line 4,145 ⟶ 4,218:
=={{header|Ruby}}==
<
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| ID |
Line 4,173 ⟶ 4,246:
table.each{|el| p el.values}; puts
table.each{|el| puts "%7s, %2d bits: %s" % [el.name, el.bits, binstr[el.range] ]}
</syntaxhighlight>
{{out}}
<pre>["ID", 16, 0...16]
Line 4,215 ⟶ 4,288:
See the output below the source code.
<
pub type Bit = bool;
Line 4,605 ⟶ 4,678:
}) => eprintln!("Could not parse the input: {:?}", e),
}
}</
{{out}}
Line 4,679 ⟶ 4,752:
In this implementation, '''parse''' produces a dictionary from names to bit-lengths. '''encode''' and '''decode''' use these to produce appropriate binary format strings, and then do what they say on the tin. As implemented, this is limited to unsigned numeric values in fields. Supporting unsigned values, strings and enums would require parsing a more complex annotation than only the ASCII art packet structure, but ought not take much more code.
<syntaxhighlight lang="tcl">
namespace eval asciipacket {
proc assert {expr} { ;# for "static" assertions that throw nice errors
Line 4,757 ⟶ 4,830:
}
}
</syntaxhighlight>
And here is how to use it with the original test data:
<syntaxhighlight lang="tcl">
proc test {} {
set header {
Line 4,799 ⟶ 4,872:
}
test
</syntaxhighlight>
{{Out}}
<pre>
Line 4,816 ⟶ 4,889:
decoded(TC) = 0
decoded(Z) = 100
</pre>
=={{header|V (Vlang)}}==
{{trans|go}}
<syntaxhighlight lang="v (vlang)">import math.big
import strings
struct Result {
name string
size int
start int
end int
}
fn (r Result) str() string {
return "${r.name:-7} ${r.size:2} ${r.start:3} ${r.end:3}"
}
fn validate(diagram string) ?[]string {
mut lines := []string{}
for mut line in diagram.split("\n") {
line = line.trim(" \t")
if line != "" {
lines << line
}
}
if lines.len == 0 {
return error("diagram has no non-empty lines!")
}
width := lines[0].len
cols := (width - 1) / 3
if cols != 8 && cols != 16 && cols != 32 && cols != 64 {
return error("number of columns should be 8, 16, 32 or 64")
}
if lines.len%2 == 0 {
return error("number of non-empty lines should be odd")
}
if lines[0] != "${strings.repeat_string("+--", cols)}+" {
return error("incorrect header line")
}
for i, line in lines {
if i == 0 {
continue
} else if i%2 == 0 {
if line != lines[0] {
return error("incorrect separator line")
}
} else if line.len != width {
return error("inconsistent line widths")
} else if line[0..1] != '|' || line[width-1..width] != '|' {
return error("non-separator lines must begin and end with '|'")
}
}
return lines
}
fn decode(lines []string) []Result {
println("Name Bits Start End")
println("======= ==== ===== ===")
mut start := 0
width := lines[0].len
mut results := []Result{}
for i, l in lines {
if i%2 == 0 {
continue
}
line := l[1..width-1]
for n in line.split("|") {
mut name := n
size := (name.len + 1) / 3
name = name.trim_space()
res := Result{name, size, start, start + size - 1}
results << res
println(res)
start += size
}
}
return results
}
fn unpack(results []Result, hex string) {
println("\nTest string in hex:")
println(hex)
println("\nTest string in binary:")
bin := hex2bin(hex) or {'ERROR'}
println(bin)
println("\nUnpacked:\n")
println("Name Size Bit pattern")
println("======= ==== ================")
for res in results {
println("${res.name:-7} ${res.size:2} ${bin[res.start..res.end+1]}")
}
}
fn hex2bin(hex string) ?string {
z := big.integer_from_radix(hex, 16)?
return "${z.binary_str():096}"
}
fn main() {
diagram := '
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| ID |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|QR| Opcode |AA|TC|RD|RA| Z | RCODE |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| QDCOUNT |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| ANCOUNT |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| NSCOUNT |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| ARCOUNT |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
'
lines := validate(diagram)?
println("Diagram after trimming whitespace and removal of blank lines:\n")
for line in lines {
println(line)
}
println("\nDecoded:\n")
results := decode(lines)
hex := "78477bbf5496e12e1bf169a4" // test string
unpack(results, hex)
}</syntaxhighlight>
{{out}}
<pre>
Same as Go entry
</pre>
Line 4,823 ⟶ 5,026:
{{libheader|Wren-fmt}}
{{libheader|Wren-big}}
<
import "./fmt" for Fmt
import "./big" for BigInt
var Result = Tuple.create("Result", ["name", "size", "start", "end"])
Line 4,928 ⟶ 5,131:
var results = decode.call(lines)
var hex = "78477bbf5496e12e1bf169a4" // test string
unpack.call(results, hex)</
{{out}}
|