Skip to content

Commit 1e8e0bf

Browse files
committed
add #g read macro for reading binary base64 encoding float/integer array
1 parent 74fff34 commit 1e8e0bf

File tree

3 files changed

+231
-0
lines changed

3 files changed

+231
-0
lines changed

lisp/c/eus_proto.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -334,6 +334,7 @@ extern pointer makeclass(context */*ctx*/, pointer /*name*/, pointer /*superobj*
334334
extern pointer makeobject(pointer /*class*/);
335335
extern pointer makevector(pointer /*vclass*/, int /*size*/);
336336
extern pointer makefvector(int /*s*/);
337+
extern pointer makeivector(int /*s*/);
337338
extern pointer defvector(context */*ctx*/, char */*name*/, pointer /*super*/, int /*elm*/, int /*size*/);
338339
extern pointer makematrix(context */*ctx*/, int /*row*/, int /*column*/);
339340
extern pointer makemodule(context */*ctx*/, int /*size*/);

lisp/c/makes.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -443,6 +443,14 @@ register int s;
443443
v->c.vec.size=makeint(s);
444444
return(v);}
445445

446+
pointer makeivector(s)
447+
register int s;
448+
{ register pointer v;
449+
register bpointer b;
450+
v=alloc(s+1,ELM_INT, intvectorcp.cix,s+1);
451+
v->c.vec.size=makeint(s);
452+
return(v);}
453+
446454
pointer defvector(ctx,name,super,elm,size) /*define vector class*/
447455
register context *ctx;
448456
char *name;

lisp/c/reader.c

Lines changed: 222 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -450,6 +450,227 @@ register pointer s; /*input stream*/
450450
}
451451
vpop();
452452
return(result); }
453+
454+
static int base64tobin (char c) {
455+
if('A' <= c && c <= 'Z') return (c - 'A');
456+
if('a' <= c && c <= 'z') return (c - 'a' + 26);
457+
if('0' <= c && c <= '9') return (c - '0' + 52);
458+
if(c == '+') return 62;
459+
if(c == '/') return 63;
460+
if(c == '=') return '=';
461+
error(E_USER, (pointer)"invalid base64 character");
462+
}
463+
static pointer readbinaryarray(context *ctx, pointer s, pointer subchr, pointer val)
464+
{
465+
register pointer elm;
466+
numunion nu;
467+
int i, ch;
468+
unsigned long size;
469+
int rank;
470+
int dim[ARRAYRANKLIMIT];
471+
unsigned char *buffer;
472+
pointer entity;
473+
pointer ret = NIL;
474+
475+
for (i = 0; i < ARRAYRANKLIMIT; i++) dim[i] = 0;
476+
ch = nextch(ctx,s);
477+
if (ch != '(') error(E_USER, (pointer)"invalid binary array form [(]");
478+
479+
rank = 0;
480+
size = 1;
481+
elm = read1(ctx,s); // read size list
482+
while(elm != NIL) {
483+
if( isint(elm->c.cons.car) ) {
484+
dim[rank] = intval(elm->c.cons.car);
485+
size *= dim[rank];
486+
rank++;
487+
}
488+
elm = elm->c.cons.cdr;
489+
}
490+
elm = read1(ctx,s); // read elemtype
491+
ch = nextch(ctx,s);
492+
if (ch != '"') {
493+
error(E_USER, (pointer)"invalid binary array form [\"]");
494+
}
495+
496+
if (elm == K_FLOAT || elm == K_FLOAT32) {
497+
entity = makefvector(size);
498+
#ifdef x86_64
499+
buffer = malloc(sizeof(float) * size);
500+
#else
501+
buffer = (unsigned char *) &(entity->c.fvec.fv[0]);
502+
#endif
503+
size *= 4;
504+
} else if (elm == K_DOUBLE) {
505+
entity = makefvector(size);
506+
#ifdef x86_64
507+
buffer = (unsigned char *) &(entity->c.fvec.fv[0]);
508+
#else
509+
buffer = malloc(sizeof(double) * size);
510+
#endif
511+
size *= 8;
512+
} else if (elm == K_SHORT) {
513+
entity = makeivector(size);
514+
buffer = malloc(sizeof(short) * size);
515+
size *= 2;
516+
} else if (elm == K_INTEGER) {
517+
entity = makeivector(size);
518+
#ifdef x86_64
519+
buffer = malloc(sizeof(int) * size);
520+
#else
521+
buffer = (unsigned char *) &(entity->c.ivec.iv[0]);
522+
#endif
523+
size *= 4;
524+
} else if (elm == K_LONG) {
525+
entity = makeivector(size);
526+
#ifdef x86_64
527+
buffer = (unsigned char *) &(entity->c.ivec.iv[0]);
528+
#else
529+
buffer = malloc(sizeof(long long) * size);
530+
#endif
531+
size *= 8;
532+
} else {
533+
error(E_USER, (pointer)"invalid binary element type");
534+
}
535+
vpush(entity);
536+
if(rank == 1) {
537+
// return vector
538+
ret = entity;
539+
vpop();
540+
vpush(ret);
541+
} else {
542+
// make array
543+
ret = alloc(vecsize(speval(ARRAY)->c.cls.vars), ELM_FIXED,
544+
intval(speval(ARRAY)->c.cls.cix),
545+
vecsize(speval(ARRAY)->c.cls.vars));
546+
ret->c.ary.entity = entity;
547+
vpop();
548+
vpush(ret);
549+
ret->c.ary.fillpointer = NIL;
550+
ret->c.ary.rank = makeint(rank);
551+
ret->c.ary.offset = makeint(0);
552+
for (i = 0; i < ARRAYRANKLIMIT; i++) ret->c.ary.dim[i] = makeint(dim[i]);
553+
ret->c.ary.plist = NIL;
554+
}
555+
556+
int strsize = (size*8+5)/6;
557+
strsize = ((strsize+3)/4)*4;
558+
// read string
559+
char *ascstr = malloc(strsize);
560+
i = 0;
561+
while((ch = readch(s)) != EOF) {
562+
ascstr[i++] = ch;
563+
if(i >= strsize) break;
564+
}
565+
if(i != strsize) {
566+
free(ascstr);
567+
vpop();
568+
error(E_USER, (pointer)"invalid size of string");
569+
}
570+
ch = readch(s);
571+
if (ch != '"') {
572+
free(ascstr);
573+
vpop();
574+
error(E_USER, (pointer)"invalid binary array form / end of [\"]");
575+
}
576+
577+
// decode base64
578+
{
579+
int asc_cntr = 0;
580+
int buf_cntr = 0;
581+
int mode = 0;
582+
int current_bin;
583+
while (asc_cntr < strsize) {
584+
int base64char = base64tobin(ascstr[asc_cntr++]);
585+
if (base64char != 77) {
586+
switch (mode) {
587+
case 0:
588+
current_bin = (base64char << 2);
589+
break;
590+
case 1:
591+
current_bin |= (base64char >> 4);
592+
buffer[buf_cntr++] = current_bin;
593+
current_bin = (base64char & 0x0f) << 4;
594+
break;
595+
case 2:
596+
current_bin |= (base64char >> 2);
597+
buffer[buf_cntr++] = current_bin;
598+
current_bin = (base64char & 0x03) << 6;
599+
break;
600+
case 3:
601+
current_bin |= base64char;
602+
buffer[buf_cntr++] = current_bin;
603+
break;
604+
}
605+
mode = (mode+1) % 4;
606+
}
607+
}
608+
if(mode > 0) buffer[buf_cntr++] = current_bin;
609+
}
610+
free(ascstr);
611+
612+
613+
if (elm == K_FLOAT || elm == K_FLOAT32) {
614+
#ifdef x86_64
615+
float *src = (float *)buffer;
616+
eusfloat_t *dst = (eusfloat_t *)&(entity->c.fvec.fv[0]);
617+
for (i = 0; i < size/4; i++) {
618+
*dst++ = *src++;
619+
}
620+
free(buffer);
621+
#else
622+
// do nothing
623+
#endif
624+
} else if (elm == K_DOUBLE) {
625+
#ifdef x86_64
626+
// do nothing
627+
#else
628+
double *src = (double *)buffer;
629+
eusfloat_t *dst = (eusfloat_t *)&(entity->c.fvec.fv[0]);
630+
for (i = 0; i < size/8; i++) {
631+
*dst++ = *src++;
632+
}
633+
free(buffer);
634+
#endif
635+
} else if (elm == K_SHORT) {
636+
short *src = (short *)buffer;
637+
eusinteger_t *dst = (eusinteger_t *)&(entity->c.ivec.iv[0]);
638+
for (i = 0; i < size/2; i++) {
639+
*dst++ = *src++;
640+
}
641+
free(buffer);
642+
} else if (elm == K_INTEGER) {
643+
#ifdef x86_64
644+
int *src = (int *)buffer;
645+
eusinteger_t *dst = (eusinteger_t *)&(entity->c.ivec.iv[0]);
646+
for (i = 0; i < size/4; i++) {
647+
*dst++ = *src++;
648+
}
649+
free(buffer);
650+
#else
651+
// do nothing
652+
#endif
653+
} else if (elm == K_LONG) {
654+
#ifdef x86_64
655+
// do nothing
656+
#else
657+
long long *src = (long long *)buffer;
658+
eusinteger_t *dst = (eusinteger_t *)&(entity->c.ivec.iv[0]);
659+
for (i = 0; i < size/8; i++) {
660+
*dst++ = *src++;
661+
}
662+
free(buffer);
663+
#endif
664+
}
665+
//
666+
ch=nextch(ctx,s);
667+
while (ch!=')' && ch!=EOF) {
668+
ch=nextch(ctx,s);
669+
}
670+
671+
return vpop();
672+
}
673+
453674

454675
/****************************************************************/
455676
/* read dispatch macro expression
@@ -1058,6 +1279,7 @@ register context *ctx;
10581279
sharpmacro['I']=makeint((eusinteger_t)readivector);
10591280
sharpmacro['J']=makeint((eusinteger_t)readobject);
10601281
sharpmacro['V']=makeint((eusinteger_t)readobject);
1282+
sharpmacro['G']=makeint((eusinteger_t)readbinaryarray);
10611283

10621284
/* make default readtable */
10631285
rdtable=(pointer)makereadtable(ctx);

0 commit comments

Comments
 (0)