Sort-Key-LargeInt

 view release on metacpan or  search on metacpan

LargeInt.xs  view on Meta::CPAN

/* -*- Mode: C -*- */

#define PERL_NO_GET_CONTEXT 1

#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"

#include "ppport.h"

MODULE = Sort::Key::LargeInt		PACKAGE = Sort::Key::LargeInt		

void
encode_largeint(li=NULL)
    SV *li
PPCODE:
    if (!li) 
        li = DEFSV;
    {
	STRLEN len;
	const char *li_pv = SvPV(li, len);
	STRLEN i;
	int neg = 0;
	const char *from;
	const char *start;
	const char *top = li_pv + len;
	STRLEN digits;
	STRLEN chunks;
	STRLEN retlen;
	SV *ret;
	char *ret_pv;
	char *to;

	start = li_pv;

	/* look for sign */
	if (len) {
	    if (*start == '-') {
		start++;
		neg = 1;
	    }
	    else if (*start == '+') {
		start++;
	    }
	}

	/* discard zeros at the left */
	for (; start < top && (*start == '0' || *start == '_'); start++);

	/* count the number of digits in order to preallocate the returned SV buffer */
	for (digits = 0, from = start; from < top; from++) {
	    if (*from >= '0' && *from <= '9')
		digits++;
	    else if (*from != '_')
		break;
	}

	/* calculate target length */
	chunks = (digits + 8 ) / 9;
	retlen = chunks / 127 + 1 + chunks * 4 + 1;

	ret = sv_2mortal(newSV(retlen));
	SvPOK_on(ret);
	to = ret_pv = SvPV_nolen(ret);
	
	/* store number length prefix with sign */
	for (i = chunks; i >= 127; i -= 127)
	    *(to++) = (neg ? 1 : 255);
	*(to++) = (neg ? 128 - i : 128 + i);

	/* compress number */
	from = start;
	while (digits) {
	    int digits_in_chunk = (digits - 1) % 9 + 1;
	    U32 acu = 0;
	    for (i = 0; i < digits_in_chunk; i++, from++) {



( run in 1.044 second using v1.01-cache-2.11-cpan-5511b514fd6 )