|
| 1 | + |
| 2 | + |
| 3 | +(module |
| 4 | + (memory (export "mem") 2) |
| 5 | + |
| 6 | + (data $digits (i32.const 0) "\77\24\5d\6d\2e\6b\7b\25\7f\6f") |
| 7 | + |
| 8 | + (global $lineBreak i32 (i32.const 10)) |
| 9 | + (global $vertical i32 (i32.const 124)) |
| 10 | + (global $horizontal i32 (i32.const 95)) |
| 11 | + (global $zero i32 (i32.const 48)) |
| 12 | + (global $unknown i32 (i32.const 63)) |
| 13 | + (global $comma i32 (i32.const 44)) |
| 14 | + (global $outputOffset i32 (i32.const 256)) |
| 15 | + |
| 16 | + ;; |
| 17 | + ;; Converts 7-bit multi-character numbers into a number string |
| 18 | + ;; |
| 19 | + ;; @param {i32} $inputOffset - offset of the input in linear memory |
| 20 | + ;; @param {i32} $inputLength - length of the input in linear memory |
| 21 | + ;; |
| 22 | + ;; @returns {(i32,i32)} - offset and length of output in linear memory |
| 23 | + (func (export "convert") (param $inputOffset i32) (param $inputLength i32) (result i32 i32) |
| 24 | + (local $inputPos i32) |
| 25 | + (local $inputPtr i32) |
| 26 | + (local $lineLength i32) |
| 27 | + (local $lines i32) |
| 28 | + (local $digit i32) |
| 29 | + (local $outputLength i32) |
| 30 | + (local.set $lineLength (i32.const -1)) |
| 31 | + (loop $measureLine |
| 32 | + (local.set $lineLength (i32.add (local.get $lineLength) (i32.const 1))) |
| 33 | + (br_if $measureLine |
| 34 | + (i32.ne (i32.load8_u (i32.add (local.get $inputOffset) |
| 35 | + (local.get $lineLength))) |
| 36 | + (global.get $lineBreak))) |
| 37 | + ) |
| 38 | + (local.set $lineLength (i32.add (local.get $lineLength) (i32.const 1))) |
| 39 | + (loop $readDigits |
| 40 | + (local.set $inputPtr (i32.add (local.get $inputOffset) (local.get $inputPos))) |
| 41 | + ;; generate bitmask from segments |
| 42 | + (local.set $lines (i32.or (i32.or (i32.or (i32.or (i32.or (i32.or |
| 43 | + ;; bit 1: top |
| 44 | + (i32.eq (i32.load8_u (i32.add (local.get $inputPtr) (i32.const 1))) |
| 45 | + (global.get $horizontal)) |
| 46 | + ;; bit 2: upper left |
| 47 | + (i32.shl (i32.eq (i32.load8_u (i32.add (local.get $inputPtr) |
| 48 | + (local.get $lineLength))) (global.get $vertical)) (i32.const 1))) |
| 49 | + ;; bit 3: upper right |
| 50 | + (i32.shl (i32.eq (i32.load8_u (i32.add (i32.add (local.get $inputPtr) |
| 51 | + (local.get $lineLength)) (i32.const 2))) (global.get $vertical)) (i32.const 2))) |
| 52 | + ;; bit 4: middle |
| 53 | + (i32.shl (i32.eq (i32.load8_u (i32.add (i32.add (local.get $inputPtr) |
| 54 | + (local.get $lineLength)) (i32.const 1))) (global.get $horizontal)) (i32.const 3))) |
| 55 | + ;; bit 5: lower left |
| 56 | + (i32.shl (i32.eq (i32.load8_u (i32.add (local.get $inputPtr) |
| 57 | + (i32.shl (local.get $lineLength) (i32.const 1)))) |
| 58 | + (global.get $vertical)) (i32.const 4))) |
| 59 | + ;; bit 6: lower right |
| 60 | + (i32.shl (i32.eq (i32.load8_u (i32.add (i32.add (local.get $inputPtr) |
| 61 | + (i32.shl (local.get $lineLength) (i32.const 1))) (i32.const 2))) |
| 62 | + (global.get $vertical)) (i32.const 5))) |
| 63 | + ;; bit 7: bottom |
| 64 | + (i32.shl (i32.eq (i32.load8_u (i32.add (i32.add (local.get $inputPtr) |
| 65 | + (i32.shl (local.get $lineLength) (i32.const 1))) (i32.const 1))) |
| 66 | + (global.get $horizontal)) (i32.const 6)))) |
| 67 | + ;; bitmask index in data is number; 10 = not found ('?') |
| 68 | + (local.set $digit (i32.const -1)) |
| 69 | + (loop $findDigit |
| 70 | + (local.set $digit (i32.add (local.get $digit) (i32.const 1))) |
| 71 | + (br_if $findDigit (i32.and (i32.lt_s (local.get $digit) (i32.const 10)) |
| 72 | + (i32.ne (local.get $lines) (i32.load8_u (local.get $digit))))) |
| 73 | + ) |
| 74 | + ;; write number or question mark |
| 75 | + (i32.store8 (i32.add (global.get $outputOffset) (local.get $outputLength)) |
| 76 | + (select (i32.add (local.get $digit) (global.get $zero)) (global.get $unknown) |
| 77 | + (i32.lt_u (local.get $digit) (i32.const 10)))) |
| 78 | + (local.set $outputLength (i32.add (local.get $outputLength) (i32.const 1))) |
| 79 | + (local.set $inputPos (i32.add (local.get $inputPos) (i32.const 3))) |
| 80 | + ;; line break |
| 81 | + (if (i32.eqz (i32.rem_u (i32.add (local.get $inputPos) (i32.const 1)) |
| 82 | + (local.get $lineLength))) (then |
| 83 | + (i32.store8 (i32.add (global.get $outputOffset) (local.get $outputLength)) (global.get $comma)) |
| 84 | + (local.set $outputLength (i32.add (local.get $outputLength) (i32.const 1))) |
| 85 | + (local.set $inputPos |
| 86 | + (i32.add (i32.add (local.get $inputPos) (i32.const 1)) |
| 87 | + (i32.mul (local.get $lineLength) (i32.const 3)))) |
| 88 | + )) |
| 89 | + (br_if $readDigits (i32.lt_u (local.get $inputPos) (local.get $inputLength))) |
| 90 | + ) |
| 91 | + ;; remove superfluous ',' |
| 92 | + (global.get $outputOffset) (i32.sub (local.get $outputLength) (i32.const 1)) |
| 93 | + ) |
| 94 | +) |
0 commit comments