diff options
author | Steve Bennett <steveb@workware.net.au> | 2013-12-12 17:25:04 +1000 |
---|---|---|
committer | Steve Bennett <steveb@workware.net.au> | 2013-12-21 01:56:58 +1000 |
commit | 52188593fcbbbbe72b81814d6d2ae11d13202af4 (patch) | |
tree | 314633aad9b3d50653c0319732963cf50dd8eb03 /jim.c | |
parent | 5390d57487b0bc2cd6ff736f50e0acbbdb6c03e7 (diff) | |
download | jimtcl-52188593fcbbbbe72b81814d6d2ae11d13202af4.zip jimtcl-52188593fcbbbbe72b81814d6d2ae11d13202af4.tar.gz jimtcl-52188593fcbbbbe72b81814d6d2ae11d13202af4.tar.bz2 |
Make identification of nan and inf more robust
Use isinf() and isnan() when converting double to string
to ensure that the value is given canonical form.
And implement our own isinf and isnan if necessary
Diffstat (limited to 'jim.c')
-rw-r--r-- | jim.c | 128 |
1 files changed, 70 insertions, 58 deletions
@@ -581,47 +581,6 @@ int Jim_StringToWide(const char *str, jim_wide * widePtr, int base) return JimCheckConversion(str, endptr); } -int Jim_DoubleToString(char *buf, double doubleValue) -{ - int len; - int i; - - len = sprintf(buf, "%.12g", doubleValue); - - /* Add a final ".0" if necessary */ - for (i = 0; i < len; i++) { - if (buf[i] == '.' || buf[i] == 'e') { -#if defined(JIM_SPRINTF_DOUBLE_NEEDS_FIX) - /* If 'buf' ends in e-0nn or e+0nn, remove - * the 0 after the + or - and reduce the length by 1 - */ - char *e = strchr(buf, 'e'); - if (e && (e[1] == '-' || e[1] == '+') && e[2] == '0') { - /* Move it up */ - e += 2; - memmove(e, e + 1, len - (e - buf)); - return len - 1; - } -#endif - return len; - } - /* inf or Infinity -> Inf, nan -> NaN */ - if (buf[i] == 'i' || buf[i] == 'I' || buf[i] == 'n' || buf[i] == 'N') { - buf[i] = toupper(UCHAR(buf[i])); - if (buf[i] == 'n' || buf[i] == 'N') - buf[i+2] = toupper(UCHAR(buf[i+2])); - buf[i + 3] = 0; - return i + 3; - } - } - - buf[i++] = '.'; - buf[i++] = '0'; - buf[i] = '\0'; - - return i; -} - int Jim_StringToDouble(const char *str, double *doublePtr) { char *endptr; @@ -2361,6 +2320,12 @@ const char *Jim_String(Jim_Obj *objPtr) return objPtr->bytes; } +static void JimSetStringBytes(Jim_Obj *objPtr, const char *str) +{ + objPtr->bytes = Jim_StrDup(str); + objPtr->length = strlen(str); +} + static void FreeDictSubstInternalRep(Jim_Interp *interp, Jim_Obj *objPtr); static void DupDictSubstInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr); @@ -5906,15 +5871,61 @@ static const Jim_ObjType doubleObjType = { JIM_TYPE_NONE, }; +#ifndef HAVE_ISNAN +#undef isnan +#define isnan(X) ((X) != (X)) +#endif +#ifndef HAVE_ISINF +#undef isinf +#define isinf(X) (1.0 / (X) == 0.0) +#endif + void UpdateStringOfDouble(struct Jim_Obj *objPtr) { - int len; - char buf[JIM_DOUBLE_SPACE + 1]; + double value = objPtr->internalRep.doubleValue; - len = Jim_DoubleToString(buf, objPtr->internalRep.doubleValue); - objPtr->bytes = Jim_Alloc(len + 1); - memcpy(objPtr->bytes, buf, len + 1); - objPtr->length = len; + if (isnan(value)) { + JimSetStringBytes(objPtr, "NaN"); + return; + } + if (isinf(value)) { + if (value < 0) { + JimSetStringBytes(objPtr, "-Inf"); + } + else { + JimSetStringBytes(objPtr, "Inf"); + } + return; + } + { + char buf[JIM_DOUBLE_SPACE + 1]; + int i; + int len = sprintf(buf, "%.12g", value); + + /* Add a final ".0" if necessary */ + for (i = 0; i < len; i++) { + if (buf[i] == '.' || buf[i] == 'e') { +#if defined(JIM_SPRINTF_DOUBLE_NEEDS_FIX) + /* If 'buf' ends in e-0nn or e+0nn, remove + * the 0 after the + or - and reduce the length by 1 + */ + char *e = strchr(buf, 'e'); + if (e && (e[1] == '-' || e[1] == '+') && e[2] == '0') { + /* Move it up */ + e += 2; + memmove(e, e + 1, len - (e - buf)); + } +#endif + break; + } + } + if (buf[i] == '\0') { + buf[i++] = '.'; + buf[i++] = '0'; + buf[i] = '\0'; + } + JimSetStringBytes(objPtr, buf); + } } int SetDoubleFromAny(Jim_Interp *interp, Jim_Obj *objPtr) @@ -7255,19 +7266,20 @@ static const Jim_ObjType indexObjType = { void UpdateStringOfIndex(struct Jim_Obj *objPtr) { - int len; - char buf[JIM_INTEGER_SPACE + 1]; - - if (objPtr->internalRep.intValue >= 0) - len = sprintf(buf, "%d", objPtr->internalRep.intValue); - else if (objPtr->internalRep.intValue == -1) - len = sprintf(buf, "end"); + if (objPtr->internalRep.intValue == -1) { + JimSetStringBytes(objPtr, "end"); + } else { - len = sprintf(buf, "end%d", objPtr->internalRep.intValue + 1); + char buf[JIM_INTEGER_SPACE + 1]; + if (objPtr->internalRep.intValue >= 0) { + sprintf(buf, "%d", objPtr->internalRep.intValue); + } + else { + /* Must be <= -2 */ + sprintf(buf, "end%d", objPtr->internalRep.intValue + 1); + } + JimSetStringBytes(objPtr, buf); } - objPtr->bytes = Jim_Alloc(len + 1); - memcpy(objPtr->bytes, buf, len + 1); - objPtr->length = len; } int SetIndexFromAny(Jim_Interp *interp, Jim_Obj *objPtr) |