/* nibbleswap.c  */
/* from: //https://www.geeksforgeeks.org/swap-two-nibbles-byte/ 
*  dated April 7, 2021  - Shivi_Aggarwal                       
* 2021-12-13 - Ray Bambery                                    
*              initial release                                 
* 2022-06-01 - Ray Bambery                                     
*              changed array size from 5 MB to 1 MB           
*              added prompt if no parameters                  
* 2022-06-06   Ray Bambery
*                put in master loop (j index) to avoid Segmentation fault (core dumped 
*                                                             
/* program to nibble  swap bytes                                */
/*                                                              */

#include <stdlib.h>
#include <stdio.h>
#include <ncurses.h>

/* prototypes   */
unsigned char swapNibbles(unsigned char x);
int maxrec = 10000000;
int MAXSIZE = 1000000;

int main(int argc, char* argv[])
{
int inerr, outerr, result, recnum;
int i, j;
FILE* in_fd;
FILE* out_fd;
unsigned char datax[1000000],datay[1000000];
//int datax[5000000],datay[5000000];

//printf ("START\n");

    if (argc < 2 ){
        printf("usage:  nibbleswap infile outfile \n");
        exit(0);
    }  


/* open input file */
    if ((in_fd = fopen(argv[1],"rb")) == NULL) {
         printf (" can't open input file %s \n",argv[1]);
        exit(0);
    }

/* open output file */
    if ((out_fd = fopen(argv[2],"wb")) == NULL) {
         printf (" can't open output file %s \n",argv[2]);
        exit(0);
    }
//    printf ("READ\n");

   for (j=0;j<maxrec;j++) {

        inerr=fread(&datax,1,MAXSIZE,in_fd);    /* read up to 5MB */
        if(inerr != 0) 
        {
            printf("\n");
            printf("  %d RECORDS nibbleswapped.\n ",inerr);

        } else {
            if(feof(in_fd)) {   //if file pointer reach to end it will break{
                printf ("reached end of file\n");
                exit(0);
            } else {
                printf ("ERROR on fread \n");
                exit(1);
            }
        }
//        printf ("> %0X %0X  %0X %0X\n",datax[0],datax[1],datax[2],datax[3]);

        for (i=0;i<recnum; i++) {
            datay[i] = swapNibbles(datax[i]);
        }
//         printf (" %X %X  %X %X\n",datay[0],datay[1],datay[2],datay[3]);


        outerr = fwrite (&datay,1,recnum,out_fd);
        if (outerr == 0) {
            printf ("ERROR on write\n");
        }
    }
fclose (in_fd);
fclose (out_fd);
}
/*******************************************************/
/*
1) The expression “x & 0x0F” gives us last 4 bits of x. 
For x = 100, the result is 00000100. 
Using bitwise ‘<<‘ operator, we shift the last four bits 
to the left 4 times and make the new last four bits as 0.
 The result after shift is 01000000.
2) The expression “x & 0xF0” gives us first four bits of x. 
For x = 100, the result is 01100000. 
Using bitwise ‘>>’ operator, we shift the digit to the 
right 4 times and make the first four bits as 0. i
The result after shift is 00000110.
*/
unsigned char  swapNibbles(unsigned char x)
{

return ( (x & 0x0F) << 4 | (x & 0xF0) >> 4 );

}
