Task: ASCII art diagram converter

C: #include <stdlib.h>
#include <stdio.h>
#include <string.h>
enum { MAX_ROWS=14, MAX_NAMES=20, NAME_SZ=80 };

char *Lines[MAX_ROWS] = {
   "  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+",
   "  |                      ID                       |",
   "  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+",
   "  |QR|   Opcode  |AA|TC|RD|RA|   Z    |   RCODE   |",
   "  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+",
   "  |                    QDCOUNT                    |",
   "  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+",
   "  |                    ANCOUNT                    |",
   "  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+",
   "  |                    NSCOUNT                    |",
   "  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+",
   "  |                    ARCOUNT                    |",
   "  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+"
};
typedef struct {
   unsigned bit3s;
   unsigned mask;
   unsigned data;
   char A[NAME_SZ+2];
}NAME_T;
NAME_T names[MAX_NAMES];
unsigned idx_name;
enum{ID,BITS,QDCOUNT,ANCOUNT,NSCOUNT,ARCOUNT,MAX_HDR};
unsigned header[MAX_HDR]; 
unsigned idx_hdr;

int  bit_hdr(char *pLine);
int  bit_names(char *pLine);
void dump_names(void);
void make_test_hdr(void);

int main(void){
   char *p1;   int rv;
   printf("Extract meta-data from bit-encoded text form\n");
   make_test_hdr();
   idx_name = 0;
   for( int i=0; i<MAX_ROWS;i++ ){
      p1 = Lines[i];
      if( p1==NULL ) break;
      if( rv = bit_hdr(Lines[i]), rv>0) continue;
      if( rv = bit_names(Lines[i]),rv>0) continue;
      
   }
   dump_names();
}

int  bit_hdr(char *pLine){ 
   char *p1 = strchr(pLine,'+');
   if( p1==NULL ) return 0;
   int numbits=0;
   for( int i=0; i<strlen(p1)-1; i+=3 ){
      if( p1[i] != '+' || p1[i+1] != '-' || p1[i+2] != '-' ) return 0;
      numbits++;
   }
   return numbits;
}

int  bit_names(char *pLine){ 
   char *p1,*p2 = pLine, tmp[80];
   unsigned sz=0, maskbitcount = 15;
   while(1){
      p1 = strchr(p2,'|');  if( p1==NULL ) break;
      p1++;
      p2 = strchr(p1,'|');  if( p2==NULL ) break;
      sz = p2-p1;
      tmp[sz] = 0;  
      int k=0;
      for(int j=0; j<sz;j++){  
	 if( p1[j] > ' ') tmp[k++] = p1[j];
      }
      tmp[k]= 0; sz++;
      NAME_T *pn = &names[idx_name++];
      strcpy(&pn->A[0], &tmp[0]);
      pn->bit3s = sz/3;
      if( pn->bit3s < 16 ){
	 for( int i=0; i<pn->bit3s; i++){
	    pn->mask |= 1 << maskbitcount--;
	 }
	 pn->data = header[idx_hdr] & pn->mask;
	 unsigned m2 = pn->mask;
	 while( (m2 & 1)==0 ){
	    m2>>=1; 
	    pn->data >>= 1;
	 }
	 if( pn->mask == 0xf ) idx_hdr++;

      }
      else{
	 pn->data = header[idx_hdr++];
      }
   }
   return sz;
}

void dump_names(void){ 
   NAME_T *pn;
   printf("-name-bits-mask-data-\n");
   for( int i=0; i<MAX_NAMES; i++ ){
      pn = &names[i];
      if( pn->bit3s < 1 ) break;
      printf("%10s %2d X%04x = %u\n",pn->A, pn->bit3s, pn->mask, pn->data);
   }
   puts("bye..");
}

void make_test_hdr(void){
   header[ID] = 1024;
   header[QDCOUNT] = 12;
   header[ANCOUNT] = 34;
   header[NSCOUNT] = 56;
   header[ARCOUNT] = 78;
   
   
   
   
   header[BITS] = 0xB50A;
}




Go: package main

import (
    "fmt"
    "log"
    "math/big"
    "strings"
)

type result struct {
    name  string
    size  int
    start int
    end   int
}

func (r result) String() string {
    return fmt.Sprintf("%-7s   %2d    %3d   %3d", r.name, r.size, r.start, r.end)
}

func validate(diagram string) []string {
    var lines []string
    for _, line := range strings.Split(diagram, "\n") {
        line = strings.Trim(line, " \t")
        if line != "" {
            lines = append(lines, line)
        }
    }
    if len(lines) == 0 {
        log.Fatal("diagram has no non-empty lines!")
    }
    width := len(lines[0])
    cols := (width - 1) / 3
    if cols != 8 && cols != 16 && cols != 32 && cols != 64 {
        log.Fatal("number of columns should be 8, 16, 32 or 64")
    }
    if len(lines)%2 == 0 {
        log.Fatal("number of non-empty lines should be odd")
    }
    if lines[0] != strings.Repeat("+--", cols)+"+" {
        log.Fatal("incorrect header line")
    }
    for i, line := range lines {
        if i == 0 {
            continue
        } else if i%2 == 0 {
            if line != lines[0] {
                log.Fatal("incorrect separator line")
            }
        } else if len(line) != width {
            log.Fatal("inconsistent line widths")
        } else if line[0] != '|' || line[width-1] != '|' {
            log.Fatal("non-separator lines must begin and end with '|'")
        }
    }
    return lines
}

func decode(lines []string) []result {
    fmt.Println("Name     Bits  Start  End")
    fmt.Println("=======  ====  =====  ===")
    start := 0
    width := len(lines[0])
    var results []result
    for i, line := range lines {
        if i%2 == 0 {
            continue
        }
        line := line[1 : width-1]
        for _, name := range strings.Split(line, "|") {
            size := (len(name) + 1) / 3
            name = strings.TrimSpace(name)
            res := result{name, size, start, start + size - 1}
            results = append(results, res)
            fmt.Println(res)
            start += size
        }
    }
    return results
}

func unpack(results []result, hex string) {
    fmt.Println("\nTest string in hex:")
    fmt.Println(hex)
    fmt.Println("\nTest string in binary:")
    bin := hex2bin(hex)
    fmt.Println(bin)
    fmt.Println("\nUnpacked:\n")
    fmt.Println("Name     Size  Bit pattern")
    fmt.Println("=======  ====  ================")
    for _, res := range results {
        fmt.Printf("%-7s   %2d   %s\n", res.name, res.size, bin[res.start:res.end+1])
    }
}

func hex2bin(hex string) string {
    z := new(big.Int)
    z.SetString(hex, 16)
    return fmt.Sprintf("%0*b", 4*len(hex), z)
}

func main() {
    const diagram = `
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
         |                      ID                       |
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        |QR|   Opcode  |AA|TC|RD|RA|   Z    |   RCODE   |
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        |                    QDCOUNT                    |
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+

        |                    ANCOUNT                    |
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        |                    NSCOUNT                    |
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        |                    ARCOUNT                    |
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    `
    lines := validate(diagram)
    fmt.Println("Diagram after trimming whitespace and removal of blank lines:\n")
    for _, line := range lines {
        fmt.Println(line)
    }
    fmt.Println("\nDecoded:\n")
    results := decode(lines)
    hex := "78477bbf5496e12e1bf169a4" 
    unpack(results, hex)
}