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;
}





Java: import java.math.BigInteger;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

public class AsciiArtDiagramConverter {

    private static final String TEST = "+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+\r\n" +
            "|                      ID                       |\r\n" +
            "+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+\r\n" +
            "|QR|   Opcode  |AA|TC|RD|RA|   Z    |   RCODE   |\r\n" +
            "+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+\r\n" +
            "|                    QDCOUNT                    |\r\n" +
            "+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+\r\n" +
            "|                    ANCOUNT                    |\r\n" +
            "+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+\r\n" +
            "|                    NSCOUNT                    |\r\n" +
            "+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+\r\n" +
            "|                    ARCOUNT                    |\r\n" +
            "+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+";

    public static void main(String[] args) {
        validate(TEST);
        display(TEST);
        Map<String,List<Integer>> asciiMap = decode(TEST);
        displayMap(asciiMap);
        displayCode(asciiMap, "78477bbf5496e12e1bf169a4");
    }

    private static void displayCode(Map<String,List<Integer>> asciiMap, String hex) {
        System.out.printf("%nTest string in hex:%n%s%n%n", hex);

        String bin = new BigInteger(hex,16).toString(2);

        
        int length = 0;
        for ( String code : asciiMap.keySet() ) {
            List<Integer> pos = asciiMap.get(code);
            length += pos.get(1) - pos.get(0) + 1;
        }
        while ( length > bin.length() ) {
            bin = "0" + bin;
        }
        System.out.printf("Test string in binary:%n%s%n%n", bin);

        System.out.printf("Name      Size  Bit Pattern%n");
        System.out.printf("-------- -----  -----------%n");
        for ( String code : asciiMap.keySet() ) {
            List<Integer> pos = asciiMap.get(code);
            int start = pos.get(0);
            int end   = pos.get(1);
            System.out.printf("%-8s    %2d  %s%n", code, end-start+1, bin.substring(start, end+1));
        }

    }


    private static void display(String ascii) {
        System.out.printf("%nDiagram:%n%n");
        for ( String s : TEST.split("\\r\\n") ) {
            System.out.println(s);
        }
    }

    private static void displayMap(Map<String,List<Integer>> asciiMap) {
        System.out.printf("%nDecode:%n%n");


        System.out.printf("Name      Size  Start    End%n");
        System.out.printf("-------- -----  -----  -----%n");
        for ( String code : asciiMap.keySet() ) {
            List<Integer> pos = asciiMap.get(code);
            System.out.printf("%-8s    %2d     %2d     %2d%n", code, pos.get(1)-pos.get(0)+1, pos.get(0), pos.get(1));
        }

    }

    private static Map<String,List<Integer>> decode(String ascii) {
        Map<String,List<Integer>> map = new LinkedHashMap<>();
        String[] split = TEST.split("\\r\\n");
        int size = split[0].indexOf("+", 1) - split[0].indexOf("+");
        int length = split[0].length() - 1;
        for ( int i = 1 ; i < split.length ; i += 2 ) {
            int barIndex = 1;
            String test = split[i];
            int next;
            while ( barIndex < length && (next = test.indexOf("|", barIndex)) > 0 ) {
                
                List<Integer> startEnd = new ArrayList<>();
                startEnd.add((barIndex/size) + (i/2)*(length/size));
                startEnd.add(((next-1)/size) + (i/2)*(length/size));
                String code = test.substring(barIndex, next).replace(" ", "");
                map.put(code, startEnd);
                
                barIndex = next + 1;
            }
        }

        return map;
    }

    private static void validate(String ascii) {
        String[] split = TEST.split("\\r\\n");
        if ( split.length % 2 != 1 ) {
            throw new RuntimeException("ERROR 1:  Invalid number of input lines.  Line count = " + split.length);
        }
        int size = 0;
        for ( int i = 0 ; i < split.length ; i++ ) {
            String test = split[i];
            if ( i % 2 == 0 ) {
                
                if ( ! test.matches("^\\+([-]+\\+)+$") ) {
                    throw new RuntimeException("ERROR 2:  Improper line format.  Line = " + test);
                }
                if ( size == 0 ) {
                    int firstPlus = test.indexOf("+");
                    int secondPlus = test.indexOf("+", 1);
                    size = secondPlus - firstPlus;
                }
                if ( ((test.length()-1) % size) != 0 ) {
                    throw new RuntimeException("ERROR 3:  Improper line format.  Line = " + test);
                }
                
                for ( int j = 0 ; j < test.length()-1 ; j += size ) {
                    if ( test.charAt(j) != '+' ) {
                        throw new RuntimeException("ERROR 4:  Improper line format.  Line = " + test);
                    }
                    for ( int k = j+1 ; k < j + size ; k++ ) {
                        if ( test.charAt(k) != '-' ) {
                            throw new RuntimeException("ERROR 5:  Improper line format.  Line = " + test);
                        }
                    }
                }
            }
            else {
                
                if ( ! test.matches("^\\|(\\s*[A-Za-z]+\\s*\\|)+$") ) {
                    throw new RuntimeException("ERROR 6:  Improper line format.  Line = " + test);
                }
                for ( int j = 0 ; j < test.length()-1 ; j += size ) {
                    for ( int k = j+1 ; k < j + size ; k++ ) {
                        
                        if ( test.charAt(k) == '|' ) {
                            throw new RuntimeException("ERROR 7:  Improper line format.  Line = " + test);
                        }
                    }
                }

            }
        }
    }

}