The London Perl and Raku Workshop takes place on 26th Oct 2024. If your company depends on Perl, please consider sponsoring and/or attending.
#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"


MODULE = File::Checksum		PACKAGE = File::Checksum		
PROTOTYPES: ENABLE

unsigned short
Checksum(fname, count)
	char *fname
	int count
 CODE:
 	unsigned short us_buffer;
 	unsigned long ul_sum = 0;
 	int i;
 	FILE *file = fopen(fname, "rb");
 # Our algorithm is simple, using a 32 bit accumulator (ul_sum),
 # we add sequential 16 bit words to it, and at the end, fold
 # back all the carry bits from the top 16 bits into the lower 16 bits.
 	if(file)
 		{
  		for(i = 0; i < count; i += 2)
 			if(fread(&us_buffer, sizeof(unsigned short), 1, file))
 				ul_sum += us_buffer;
 			else
 				break;
 		fclose(file);
 # Add back carry outs from top 16 bits to low 16 bits.
 # Add hi 16 to low 16.
		ul_sum = (ul_sum >> 16) + (ul_sum & 0xffff);
 # Add carry.
 		ul_sum += (ul_sum >> 16);
 # Truncate to 16 bits.	
 		RETVAL = (unsigned short)~ul_sum;	
 		}
 	else
 		RETVAL = 0;
 OUTPUT:
 	RETVAL