X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=simgear%2Fnasal%2Fstring.c;h=4855054cddd24cc1983eb0d373056c64c7b66bf3;hb=f19e83dcf10d5fced3d799c884a4654d7ada6548;hp=6d9434f726a966d6f3a0204939f8420f0f2754d1;hpb=d314164fede53ed11cb0aea9beac7c18913a025f;p=simgear.git diff --git a/simgear/nasal/string.c b/simgear/nasal/string.c index 6d9434f7..4855054c 100644 --- a/simgear/nasal/string.c +++ b/simgear/nasal/string.c @@ -8,113 +8,114 @@ // double. #define DIGITS 16 -// The minimum size we'll allocate for a string. Since a string -// structure is already 12 bytes, and each naRef that points to it is -// 8, there isn't much point in being stingy. -#define MINLEN 16 - static int tonum(unsigned char* s, int len, double* result); static int fromnum(double val, unsigned char* s); +#define LEN(s) ((s)->emblen != -1 ? (s)->emblen : (s)->data.ref.len) +#define DATA(s) ((s)->emblen != -1 ? (s)->data.buf : (s)->data.ref.ptr) + int naStr_len(naRef s) { - if(!IS_STR(s)) return 0; - return s.ref.ptr.str->len; + return IS_STR(s) ? LEN(PTR(s).str) : 0; } char* naStr_data(naRef s) { - if(!IS_STR(s)) return 0; - return s.ref.ptr.str->data; + return IS_STR(s) ? (char*)DATA(PTR(s).str) : 0; } static void setlen(struct naStr* s, int sz) { - int currSz, waste; - sz += 1; // Allow for an extra nul terminator - currSz = s->len+1 < MINLEN ? MINLEN : s->len+1; - waste = currSz - sz; // how much extra if we don't reallocate? - if(s->data == 0 || waste < 0 || waste > MINLEN) { - naFree(s->data); - s->data = naAlloc(sz < MINLEN ? MINLEN : sz); + if(s->emblen == -1 && DATA(s)) naFree(s->data.ref.ptr); + if(sz > MAX_STR_EMBLEN) { + s->emblen = -1; + s->data.ref.len = sz; + s->data.ref.ptr = naAlloc(sz+1); + } else { + s->emblen = sz; } - s->len = sz - 1; - s->data[s->len] = 0; // nul terminate + DATA(s)[sz] = 0; // nul terminate +} + +naRef naStr_buf(naRef dst, int len) +{ + setlen(PTR(dst).str, len); + naBZero(DATA(PTR(dst).str), len); + return dst; } -naRef naStr_fromdata(naRef dst, char* data, int len) +naRef naStr_fromdata(naRef dst, const char* data, int len) { if(!IS_STR(dst)) return naNil(); - setlen(dst.ref.ptr.str, len); - memcpy(dst.ref.ptr.str->data, data, len); + setlen(PTR(dst).str, len); + memcpy(DATA(PTR(dst).str), data, len); return dst; } naRef naStr_concat(naRef dest, naRef s1, naRef s2) { - struct naStr* dst = dest.ref.ptr.str; - struct naStr* a = s1.ref.ptr.str; - struct naStr* b = s2.ref.ptr.str; + struct naStr* dst = PTR(dest).str; + struct naStr* a = PTR(s1).str; + struct naStr* b = PTR(s2).str; if(!(IS_STR(s1)&&IS_STR(s2)&&IS_STR(dest))) return naNil(); - setlen(dst, a->len + b->len); - memcpy(dst->data, a->data, a->len); - memcpy(dst->data + a->len, b->data, b->len); + setlen(dst, LEN(a) + LEN(b)); + memcpy(DATA(dst), DATA(a), LEN(a)); + memcpy(DATA(dst) + LEN(a), DATA(b), LEN(b)); return dest; } naRef naStr_substr(naRef dest, naRef str, int start, int len) { - struct naStr* dst = dest.ref.ptr.str; - struct naStr* s = str.ref.ptr.str; + struct naStr* dst = PTR(dest).str; + struct naStr* s = PTR(str).str; if(!(IS_STR(dest)&&IS_STR(str))) return naNil(); - if(start + len > s->len) { dst->len = 0; dst->data = 0; return naNil(); } + if(start + len > LEN(s)) return naNil(); setlen(dst, len); - memcpy(dst->data, s->data + start, len); + memcpy(DATA(dst), DATA(s) + start, len); return dest; } int naStr_equal(naRef s1, naRef s2) { - struct naStr* a = s1.ref.ptr.str; - struct naStr* b = s2.ref.ptr.str; - if(a->data == b->data) return 1; - if(a->len != b->len) return 0; - if(memcmp(a->data, b->data, a->len) == 0) return 1; + struct naStr* a = PTR(s1).str; + struct naStr* b = PTR(s2).str; + if(DATA(a) == DATA(b)) return 1; + if(LEN(a) != LEN(b)) return 0; + if(memcmp(DATA(a), DATA(b), LEN(a)) == 0) return 1; return 0; } naRef naStr_fromnum(naRef dest, double num) { - struct naStr* dst = dest.ref.ptr.str; + struct naStr* dst = PTR(dest).str; unsigned char buf[DIGITS+8]; setlen(dst, fromnum(num, buf)); - memcpy(dst->data, buf, dst->len); + memcpy(DATA(dst), buf, LEN(dst)); return dest; } int naStr_parsenum(char* str, int len, double* result) { - return tonum(str, len, result); + return tonum((unsigned char*)str, len, result); } int naStr_tonum(naRef str, double* out) { - return tonum(str.ref.ptr.str->data, str.ref.ptr.str->len, out); + return tonum(DATA(PTR(str).str), LEN(PTR(str).str), out); } int naStr_numeric(naRef str) { double dummy; - return tonum(str.ref.ptr.str->data, str.ref.ptr.str->len, &dummy); + return tonum(DATA(PTR(str).str), LEN(PTR(str).str), &dummy); } void naStr_gcclean(struct naStr* str) { - if(str->len > MINLEN) { - naFree(str->data); - str->data = 0; - } - str->len = 0; + if(str->emblen == -1) naFree(str->data.ref.ptr); + str->data.ref.ptr = 0; + str->data.ref.len = 0; + str->emblen = -1; } //////////////////////////////////////////////////////////////////////// @@ -184,9 +185,14 @@ static int tonum(unsigned char* s, int len, double* result) int i=0, fraclen=0; double sgn=1, val, frac=0, exp=0; - // Special case, "." is not a number, even though "1." and ".0" are. - if(len == 1 && s[0] == '.') - return 0; + if(len == 1 && (*s=='.' || *s=='-' || *s=='+')) return 0; + + // Strip off the leading negative sign first, so we can correctly + // parse things like -.xxx which would otherwise confuse + // readsigned. + if(len > 1 && s[0] == '-' && s[1] != '-') { + sgn = -1; s++; len--; + } // Read the integer part i = readsigned(s, len, i, &val); @@ -199,9 +205,15 @@ static int tonum(unsigned char* s, int len, double* result) i += fraclen; } + // Nothing so far? Then the parse failed. + if(i == 0) return 0; + // Read the exponent, if any - if(i < len && (s[i] == 'e' || s[i] == 'E')) + if(i < len && (s[i] == 'e' || s[i] == 'E')) { + int i0 = i+1; i = readsigned(s, len, i+1, &exp); + if(i == i0) return 0; // Must have a number after the "e" + } // compute the result *result = sgn * (val + frac * decpow(-fraclen)) * decpow(exp); @@ -213,13 +225,13 @@ static int tonum(unsigned char* s, int len, double* result) // Very simple positive (!) integer print routine. Puts the result in // s and returns the number of characters written. Does not null -// terminate the result. +// terminate the result. Presumes at least a 32 bit integer, and +// cannot print integers larger than 9999999999. static int decprint(int val, unsigned char* s) { int p=1, i=0; if(val == 0) { *s = '0'; return 1; } - while(p <= val) p *= 10; - p /= 10; + while(p <= 999999999 && p*10 <= val) p *= 10; while(p > 0) { int count = 0; while(val >= p) { val -= p; count++; } @@ -278,7 +290,7 @@ static int fromnum(double val, unsigned char* s) if(raw[i] != '0') break; digs = i+1; - if(exp > 0 || exp < -(DIGITS+2)) { + if(exp > 0 || exp < -(DIGITS+3)) { // Standard scientific notation exp += DIGITS-1; *ptr++ = raw[0];