Code:
#include <errno.h>
#include <limits.h>
#include <ctype.h>
#include <inttypes.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
typedef signed char schar;
typedef unsigned char uchar;
typedef signed long long sllong;
typedef unsigned long long ullong;
typedef int (*int_c_void_t)();
typedef int (*int_c_pvoid_t)( void *src );
#define bitsof(T) (sizeof(T) * CHAR_BIT)
#define BASE_NUM "0123456789"
#define BASE_a2z "abcdefghijklmnopqrstuvqxyz"
#define BASE_A2Z "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
char upper_base62_text[] = BASE_NUM BASE_A2Z BASE_a2z;
char lower_base62_text[] = BASE_NUM BASE_a2z BASE_A2Z;
int rdU64_base62( int_c_pvoid_t getchr, void *source, int c,
uint base, _Bool lowercase1st, uint_least64_t *num ) {
uint i = 0;
uint_least64_t n = 0;
int rdU64_high() {
char *base_text =
lowercase1st ? lower_base62_text : upper_base62_text;
for ( i = 0; i < base && c != base_text[i]; ++i );
i = (i < base) ? i : 0;
while ( i < base && (c = getchr(source)) ) {
n *= base; n += i;
for ( i = 0; i < base && c != base_text[i]; ++i );
}
if ( num ) *num = ((i < base) ? (n * base) + i : n);
return c;
}
int rdU64_both() {
for ( i = 0; i < base &&
c != upper_base62_text[i] &&
c != lower_base62_text[i]; ++i );
i = (i < base) ? i : 0;
while ( i < base && (c = getchr(source)) ) {
n *= base;
n += i;
for ( i = 0; i < base &&
c != upper_base62_text[i] &&
c != lower_base62_text[i]; ++i );
}
if ( num ) *num = ((i < base) ? (n * base) + i : n);
return c;
}
return (base < 2) ? -1 :
((base < 37) ? rdU64_both() : ((base < 63) ? rdU64_high() : -1));
}
typedef struct num_out {
uint unSigned : 1;
uint isSigned : 1;
uint use_base : 8;
uint bitcount : 16;
uint_least64_t num;
} num_out_t;
int rdNum( int_c_pvoid_t getchr, void *source, int c, num_out_t *out ) {
num_out_t o = {0};
o.use_base = 10;
int rdUint() {
int cropH() {
int p = c;
o.num = ((c = getchr(source)) == p) ?
(uchar)(o.num) : (ushort)(o.num);
o.bitcount = (c == p) ? CHAR_BIT : bitsof(short);
return c;
}
int cropL() {
int p = c;
o.num = ((c = getchr(source)) == p) ?
(ullong)(o.num) : (ulong)(o.num);
o.bitcount = (c == p) ? bitsof(sllong) : bitsof(long);
return c;
}
int cropI() {
uint_least64_t size = 0;
uint_least64_t cropV() {
uint_least64_t bit = -1;
bit <<= size;
o.num &= (~bit);
return o.num;
}
c = ((c == 'i' || c == 'I') && isdigit((c = getchr(source)))) ?
rdU64_base62( getchr, source, c, 10, 0, &size ) : c;
o.num = (size == 64) ? (o.num) :
((size == 32) ? (uint_least32_t)(o.num) :
((size == 16) ? (uint_least16_t)(o.num) :
((size == 8) ? (uint_least8_t)(o.num) :
(size ? cropV() : (uint)(o.num)))));
o.bitcount = size ? size : bitsof(int);
return c;
}
c = getchr(source);
o.use_base = (c == 'x' || c == 'X') ? 16 :
((c == 'b' || c == 'B') ? 2 : 8);
c = (o.use_base == 8) ? c : getchr(source);
c = rdU64_base62( getchr, source, c, o.use_base, 0, &(o.num) );
if ( c == 'u' || c == 'U' ) {
c = getchr(source);
o.unSigned = 1;
}
return (c == 'l' || c == 'L') ? cropL() :
((c == 'h' || c == 'H') ? cropH() : cropI());
}
int rdVal() {
return (c == '0') ? rdUint() :
rdU64_base62( getchr, source, c, 10, 0, &(o.num) );
}
int rdInt() {
int p = c;
o.isSigned = 1;
c = getchr(source);
c = rdVal();
o.num = (p == '-') ? -(o.num) : o.num;
return c;
}
c = (c == '-' || c == '+') ? rdInt() : rdVal();
if ( out ) *out = o;
return c;
}
int rdNum2( int_c_pvoid_t getchr, void *source, int c, num_out_t *out ) {
num_out_t o = {0};
o.use_base = 10;
int rdUint() {
int cropH() {
int p = c;
o.num = ((c = getchr(source)) == p) ?
(uchar)(o.num) : (ushort)(o.num);
o.bitcount = (c == p) ? CHAR_BIT : CHAR_BIT * sizeof(short);
return c;
}
int cropL() {
int p = c;
o.num = ((c = getchr(source)) == p) ?
(ullong)(o.num) : (ulong)(o.num);
o.bitcount = (c == p) ? CHAR_BIT * sizeof(sllong) :
CHAR_BIT * sizeof(long);
return c;
}
int cropI() {
uint_least64_t size = 0;
uint_least64_t cropV() {
uint_least64_t bit = -1;
bit <<= size;
o.num &= (~bit);
return o.num;
}
switch (c) {
case 'i': case 'I':
c = getchr(source);
if ( isdigit(c) )
c = rdU64_base62( getchr, source, c, 10, 0, &size );
}
switch ( size ) {
case 64: break;
case 32: o.num = (uint_least32_t)(o.num); break;
case 16: o.num = (uint_least16_t)(o.num); break;
case 8: o.num = (uint_least8_t)(o.num); break;
case 0: o.num = (uint)(o.num);
size = CHAR_BIT * sizeof(int); break;
default: o.num = cropV();
}
o.bitcount = size;
return c;
}
c = getchr(source);
switch ( c ) {
case 'x': case 'X': o.use_base = 16; break;
case 'b': case 'B': o.use_base = 2; break;
default: o.use_base = 8;
}
c = (o.use_base == 8) ? c : getchr(source);
c = rdU64_base62( getchr, source, c, o.use_base, 0, &(o.num) );
if ( c == 'u' || c == 'U' ) {
c = getchr(source);
o.unSigned = 1;
}
switch (c) {
case 'h': case 'H': return cropH();
case 'l': case 'L': return cropL();
}
return cropI();
}
int rdVal() {
return (c == '0') ? rdUint() :
rdU64_base62( getchr, source, c, 10, 0, &(o.num) );
}
int rdInt() {
int p = c;
o.isSigned = 1;
c = getchr(source);
c = rdVal();
o.num = (p == '-') ? -(o.num) : o.num;
return c;
}
c = (c == '-' || c == '+') ? rdInt() : rdVal();
if ( out ) *out = o;
return c;
}
typedef struct str {
long pos;
long cap;
long len;
char * txt;
} str_t;
int sgetc( str_t *str ) {
return str ? (((str->pos) >= 0) ?
(((str->pos) < (str->len)) ? str->txt[(str->pos)++] : 0) : -ERANGE)
: -EADDRNOTAVAIL;
}
void printNum( str_t str ) {
num_out_t num_out = {0};
char *rdNumU = "rdNum(): %" PRIuLEAST64 "\n",
*rdNumS = "rdNum(): %" PRIdLEAST64 "\n";
str.pos = 0;
(void)rdNum( (int_c_pvoid_t)sgetc, &str, sgetc(&str), &num_out );
(void)printf( num_out.unSigned ? rdNumU : rdNumS, num_out.num );
}
void printNum2( str_t str ) {
num_out_t num_out = {0};
char *rdNumU = "rdNum2(): %" PRIuLEAST64 "\n",
*rdNumS = "rdNum2(): %" PRIdLEAST64 "\n";
str.pos = 0;
(void)rdNum2( (int_c_pvoid_t)sgetc, &str, sgetc(&str), &num_out );
(void)printf( num_out.unSigned ? rdNumU : rdNumS, num_out.num );
}
typedef volatile uint_least64_t counter_t;
#if defined( __x86_64__ ) || defined( __i386__ )
counter_t INIT_TSC( void ) {
uint32_t a, d;
__asm__ __volatile__ (
#if (defined(__x86_64__) || defined( __SSE2__ )) & defined( SYNC_MEM )
"mfence\n\t"
#endif
"xorl %%eax,%%eax\n\t"
"cpuid\n\t"
"rdtsc" : "=a" (a), "=d" (d) ::
#ifdef __x86_64__
"%rbx", "%rcx"
#else
"%ebx", "%ecx"
#endif
);
return a | ((uint64_t)d << 32);
}
void KILL_TSC( counter_t *cptr )
{
uint32_t a, d;
__asm__ __volatile__ (
"cpuid\n\t"
"rdtscp" : "=a" (a), "=d" (d) ::
#ifdef _x86_64__
"%rcx"
#else
"%ecx"
#endif
);
*cptr = (a | ((uint64_t)d << 32)) - *cptr;;
}
#else
#define INIT_TSC() time(NULL)
#define KILL_TSC(P) (*(P) = time(NULL))
#endif
int main() {
uint i, max = 3;
int c;
counter_t cinit, cstop, took1, took2;
char text[65] = {0};
str_t str = {0};
str.txt = text;
str.cap = 65;
(void)sprintf( text, "%d", rand() );
str.len = strlen( text );
(void)printf( "Random Number Generated: '%s'\n", text );
printNum( str );
printNum2( str );
puts("Testing sgetc()");
str.pos = 0;
while ( (c = sgetc(&str)) ) {
if ( c > 0 ) fputc( c, stdout );
else (void)printf("#%ld", str.pos);
}
fputc( '\n', stdout );
if ( str.pos < str.len ) return 1;
puts("Testing rdNum()");
cinit = INIT_TSC();
for ( i = 0; i < max; ++i ) {
(void)sprintf( text, "%d", rand() );
str.len = strlen( text );
(void)printf( "%s: ", text );
printNum( str );
}
KILL_TSC(&cstop);
took1 = cstop - cinit;
puts("Testing rdNum2()");
cinit = INIT_TSC();
for ( i = 0; i < max; ++i ) {
(void)sprintf( text, "%d", rand() );
str.len = strlen( text );
(void)printf( "%s, ", text );
printNum2( str );
}
KILL_TSC(&cstop);
took2 = cstop - cinit;
printf("Cycles: rdNum() %llu, rdNum2() %llu\n",
(ullong)took1, (ullong)took2 );
return 0;
}
If there's any suggetions on simplifying rdNum2() then please do suggest away, I'm gonna focus on reading character literals next in prep for string literals, also seems like while simple code likes the conditional syntax better for speed, the complex code seems to like if syntax better for speed