320 lines
6.8 KiB
C
320 lines
6.8 KiB
C
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <math.h>
|
|
#include <string.h>
|
|
#include <strings.h>
|
|
#include <stdlib.h>
|
|
#include "myc_err.h"
|
|
#include "myc_str.h"
|
|
#include "myc_buf.h"
|
|
|
|
char *StrNGet(StrBuf *buf, char *result, int reslen, int sep) {
|
|
char *b, *f, *e, quote;
|
|
int l;
|
|
|
|
if (buf->rdpos < 0 || buf->rdpos >= buf->dsize || buf->buf==NULL)
|
|
ERR_MSG("buffer corrupt");
|
|
b=buf->buf + buf->rdpos;
|
|
if (*b=='"' || *b=='\'') { /* take string within quotes (single or double) */
|
|
quote=*b; b++;
|
|
f=strchr(b, quote);
|
|
if (f==NULL)
|
|
ERR_MSG("missing '""'");
|
|
l=f-b;
|
|
if (sep == StrNONE) {
|
|
buf->rdpos=f - buf->buf + 1;
|
|
buf->seen = 0;
|
|
} else {
|
|
e=strchr(f+1, sep);
|
|
if (e==NULL) {
|
|
buf->rdpos = f - buf->buf + 1 + strlen(f+1);
|
|
buf->seen=0;
|
|
} else {
|
|
buf->rdpos = e - buf->buf + 1;
|
|
buf->seen=1;
|
|
}
|
|
}
|
|
} else {
|
|
f=strchr(b, sep);
|
|
if (f==NULL) {
|
|
l=strlen(b);
|
|
f=b+l;
|
|
buf->rdpos+=l;
|
|
buf->seen=0;
|
|
} else {
|
|
l=f-b;
|
|
buf->rdpos+=l+1;
|
|
buf->seen=1;
|
|
}
|
|
}
|
|
if (result==NULL) {
|
|
if (reslen==-1) { /* special case for StrGetBuf */
|
|
return(f);
|
|
}
|
|
*f='\0';
|
|
return(b);
|
|
} else {
|
|
if (l>=reslen) l=reslen-1; /* ERR_MSG("result too short"); */
|
|
strncpy(result, b, l);
|
|
result[l]='\0';
|
|
return(result);
|
|
}
|
|
OnError:
|
|
buf->rdpos=buf->dsize; /* illegal value */
|
|
return(NULL);
|
|
}
|
|
|
|
int StrGetBuf(StrBuf *buf, StrBuf *res, int sep) {
|
|
char *b, *f;
|
|
|
|
b = buf->buf + buf->rdpos;
|
|
ERR_P(f=StrNGet(buf, NULL, -1, sep));
|
|
res->buf = b;
|
|
res->wrpos = f-b;
|
|
res->rdpos = 0;
|
|
res->dsize = f-b;
|
|
return(0);
|
|
OnError:
|
|
buf->rdpos=buf->dsize; /* illegal value */
|
|
return(-1);
|
|
}
|
|
|
|
int StrGetInt(StrBuf *buf, int *res, int sep) {
|
|
char num[32];
|
|
int i, l, p;
|
|
|
|
p=buf->rdpos;
|
|
ERR_P(StrGet(buf, num, sep));
|
|
i=sscanf(num, "%d%n", res, &l);
|
|
if (i==0)
|
|
ERR_MSG("illegal number");
|
|
if (sep==StrNONE) {
|
|
buf->rdpos=p+l;
|
|
}
|
|
return(0);
|
|
OnError:
|
|
buf->rdpos=buf->dsize; /* illegal value */
|
|
return(0);
|
|
}
|
|
|
|
int StrGetFloat(StrBuf *buf, float *res, int sep) {
|
|
char num[32];
|
|
int i, l, p;
|
|
|
|
p=buf->rdpos;
|
|
ERR_P(StrGet(buf, num, sep));
|
|
if (num[0]=='N' && num[1]=='a' && num[2]=='N') {
|
|
l=3;
|
|
*res = MYC_NAN;
|
|
} else {
|
|
i=sscanf(num, "%f%n", res, &l);
|
|
if (i==0) {
|
|
ERR_MSG("illegal number");
|
|
}
|
|
}
|
|
if (sep==StrNONE) {
|
|
buf->rdpos=p+l;
|
|
}
|
|
return(0);
|
|
OnError:
|
|
buf->rdpos=buf->dsize; /* illegal value */
|
|
return(-1);
|
|
}
|
|
|
|
int StrGetEnd(StrBuf *buf) {
|
|
if (buf->buf!=NULL) {
|
|
if (buf->rdpos < 0 || buf->rdpos >= buf->dsize)
|
|
ERR_MSG("buffer corrupt");
|
|
if (buf->rdpos != buf->wrpos)
|
|
ERR_MSG("superflous content in buffer");
|
|
}
|
|
return(0);
|
|
OnError:
|
|
return(-1);
|
|
}
|
|
|
|
int StrPut(StrBuf *buf, const char *str, int sep) {
|
|
int l, pos;
|
|
char quote;
|
|
|
|
pos=buf->wrpos;
|
|
if (pos < 0 || pos >= buf->dsize || buf->buf==NULL)
|
|
ERR_MSG("buffer corrupt");
|
|
l=strlen(str);
|
|
quote='\0';
|
|
if (sep>0) {
|
|
if (strchr(str, sep)!=NULL) {
|
|
if (strchr(str, '"')!=NULL) {
|
|
quote='"'; l+=2;
|
|
}
|
|
if (strchr(str, '\'')!=NULL) {
|
|
if (quote!='\0')
|
|
ERR_MSG("str must not contain separator and both kind of quotes");
|
|
quote='\''; l+=2;
|
|
}
|
|
}
|
|
}
|
|
if (pos+l >= buf->dsize) {
|
|
ERR_MSG("buffer too short");
|
|
}
|
|
if (quote!='\0') {
|
|
buf->buf[pos]=quote; pos++;
|
|
strcpy(buf->buf + pos, str);
|
|
buf->buf[pos]=quote; pos++;
|
|
} else {
|
|
strcpy(buf->buf + pos, str);
|
|
}
|
|
pos+=l;
|
|
if (sep!=StrNONE) {
|
|
buf->buf[pos]=sep;
|
|
pos++;
|
|
} else {
|
|
buf->buf[pos]='\0';
|
|
}
|
|
buf->wrpos=pos;
|
|
return(0);
|
|
OnError:
|
|
buf->wrpos=-1;
|
|
return(-1);
|
|
}
|
|
|
|
int StrPutInt(StrBuf *buf, int val, int sep) {
|
|
char num[32];
|
|
|
|
sprintf(num, "%d", val);
|
|
ERR_I(StrPut(buf, num, sep));
|
|
return(0);
|
|
OnError:
|
|
return(-1);
|
|
}
|
|
|
|
int StrPutFloat(StrBuf *buf, float val, int sep) {
|
|
char num[32];
|
|
|
|
if (val == MYC_NAN) {
|
|
ERR_I(StrPut(buf, "NaN", sep));
|
|
} else {
|
|
sprintf(num, "%g", val);
|
|
ERR_I(StrPut(buf, num, sep));
|
|
}
|
|
return(0);
|
|
OnError:
|
|
return(-1);
|
|
}
|
|
|
|
void StrReset(StrBuf *buf) {
|
|
buf->rdpos=0;
|
|
}
|
|
|
|
void StrClear(StrBuf *buf) {
|
|
buf->rdpos=0;
|
|
buf->wrpos=0;
|
|
}
|
|
|
|
void StrNLink(StrBuf *buf, char *str, int length) {
|
|
int l;
|
|
buf->buf=str;
|
|
buf->rdpos=0;
|
|
l=strlen(str);
|
|
if (l<length) l=length;
|
|
buf->wrpos=l;
|
|
buf->dsize=buf->wrpos;
|
|
}
|
|
|
|
#define TWO_23 8388608
|
|
#define EXP_OFFS 128
|
|
|
|
void flt_to_char4(double f, char buf[4]) {
|
|
double m;
|
|
int e;
|
|
long res;
|
|
|
|
m = frexp(f, &e);
|
|
e += EXP_OFFS;
|
|
if (e < 0 || m == 0) {
|
|
res = 0; m = 0;
|
|
} else {
|
|
if (e > 255) {
|
|
res = 255 * TWO_23 + (TWO_23 - 1); /* max. representable number */
|
|
} else {
|
|
res = (long)(0.5 + (fabs(m * 2) - 1.0) * TWO_23);
|
|
/* here we may think about the case, where m is just a little less than 1.0:
|
|
the mantissa part overflows to bit23, but, the result would be o.k., since this
|
|
just increases the exponent by one, and the mantissa bits get all zero.
|
|
but what happens when e is already 255 ? the next line handles this */
|
|
if (res == TWO_23 && e == 255) res--;
|
|
res += e * TWO_23;
|
|
}
|
|
}
|
|
buf[0] = res % 256; res = res / 256;
|
|
buf[1] = res % 256; res = res / 256;
|
|
buf[2] = res % 256; res = res / 256;
|
|
if (m < 0) {
|
|
buf[3] = res - 128;
|
|
} else {
|
|
buf[3] = res;
|
|
}
|
|
}
|
|
|
|
double flt_from_char4(char buf[4]) {
|
|
long i, b0, b1, b2, b3;
|
|
|
|
b0=buf[0]; if (b0<0) b0+=256;
|
|
b1=buf[1]; if (b1<0) b1+=256;
|
|
b2=buf[2]; if (b2<0) b2+=256;
|
|
b3=buf[3]; if (b3<0) b3+=256;
|
|
if (b3>=128) {
|
|
i=(b3-128)*(256*65536)+b2*65536+b1*256+b0;
|
|
if (i==0) return 0.0;
|
|
return -ldexp((i % TWO_23)*1.0/(TWO_23)*0.5+0.5, i/TWO_23-EXP_OFFS);
|
|
} else {
|
|
i=b3*(256*65536)+b2*65536+b1*256+b0;
|
|
if (i==0) return 0.0;
|
|
return ldexp((i % TWO_23)*1.0/(TWO_23)*0.5+0.5, i/TWO_23-EXP_OFFS);
|
|
}
|
|
}
|
|
|
|
int StrPutArray(StrBuf *buf, float val[], int size) {
|
|
int i, pos;
|
|
char *b;
|
|
|
|
pos=buf->wrpos;
|
|
if (pos < 0 || pos >= buf->dsize || buf->buf==NULL)
|
|
ERR_MSG("buffer corrupt");
|
|
if (pos+4*size >= buf->dsize)
|
|
ERR_MSG("buffer too short");
|
|
b=buf->buf+pos;
|
|
flt_to_char4((float)size, b);
|
|
b+=4;
|
|
for (i=0; i<size; i++) {
|
|
flt_to_char4(val[i], b);
|
|
b+=4;
|
|
}
|
|
buf->wrpos=b - buf->buf;
|
|
return(0);
|
|
OnError:
|
|
buf->wrpos=-1;
|
|
return(-1);
|
|
}
|
|
|
|
int StrGetArray(StrBuf *buf, float val[], int maxsize) {
|
|
int size, i;
|
|
char *b;
|
|
double gg;
|
|
|
|
if (buf->rdpos < 0 || buf->rdpos >= buf->dsize || buf->buf==NULL)
|
|
ERR_MSG("buffer corrupt");
|
|
b=buf->buf + buf->rdpos;
|
|
size=flt_from_char4(b); b+=4;
|
|
buf->rdpos+=4*(size+1);
|
|
if (maxsize<size) size=maxsize;
|
|
for (i=0; i<size; i++) {
|
|
gg=flt_from_char4(b); b+=4;
|
|
val[i]=gg;
|
|
}
|
|
return size;
|
|
OnError:
|
|
buf->rdpos=buf->dsize; /* illegal value */
|
|
return(-1);
|
|
}
|