/* * Converts string values such as TRUE/FALSE/true/false etc to 1/0/NULL. * Switched from byte-to-byte compare to library function strncasecmp, * experiments showed that library function is even slightly faster and we * now also support True/False (and trUe/FAlSE should this become a thing). */ ssize_t bitFromStr(const char *src, size_t *len, bit **dst, bool external) { const char *p = src; atommem(sizeof(bit)); **dst = bit_nil; if (GDK_STRNIL(src)) return 1; while (GDKisspace(*p)) p++; if (*p == '0') { **dst = FALSE; p++; } else if (*p == '1') { **dst = TRUE; p++; } else if (strncasecmp(p, "true", 4) == 0) { **dst = TRUE; p += 4; } else if (strncasecmp(p, "false", 5) == 0) { **dst = FALSE; p += 5; } else if (external && strncasecmp(p, "nil", 3) == 0) { p += 3; } else { return -1; } while (GDKisspace(*p)) p++; return (ssize_t) (p - src); }
/* * String conversion routines. */ ssize_t OIDfromStr(const char *src, size_t *len, oid **dst, bool external) { #if SIZEOF_OID == SIZEOF_INT int ui = 0, *uip = &ui; #else lng ui = 0, *uip = &ui; #endif size_t l = sizeof(ui); ssize_t pos = 0; const char *p = src; atommem(sizeof(oid)); **dst = oid_nil; if (GDK_STRNIL(src)) return 1; while (GDKisspace(*p)) p++; if (external && strncmp(p, "nil", 3) == 0) return (ssize_t) (p - src) + 3; if (GDKisdigit(*p)) { #if SIZEOF_OID == SIZEOF_INT pos = intFromStr(p, &l, &uip, external); #else pos = lngFromStr(p, &l, &uip, external); #endif if (pos < 0) return pos; if (p[pos] == '@') { pos++; while (GDKisdigit(p[pos])) pos++; } if (ui >= 0) { **dst = ui; } p += pos; } else { GDKerror("not an OID\n"); return -1; } while (GDKisspace(*p)) p++; return (ssize_t) (p - src); }
ssize_t dblFromStr(const char *src, size_t *len, dbl **dst, bool external) { const char *p = src; ssize_t n = 0; double d; /* alloc memory */ atommem(sizeof(dbl)); if (GDK_STRNIL(src)) { **dst = dbl_nil; return 1; } while (GDKisspace(*p)) p++; if (external && strncmp(p, "nil", 3) == 0) { **dst = dbl_nil; p += 3; n = (ssize_t) (p - src); } else { /* on overflow, strtod returns HUGE_VAL and sets * errno to ERANGE; on underflow, it returns a value * whose magnitude is no greater than the smallest * normalized double, and may or may not set errno to * ERANGE. We accept underflow, but not overflow. */ char *pe; errno = 0; d = strtod(p, &pe); if (p == pe) p = src; /* nothing converted */ else p = pe; n = (ssize_t) (p - src); if (n == 0 || (errno == ERANGE && (d < -1 || d > 1)) || !isfinite(d) /* no NaN or Infinte */ ) { GDKerror("overflow or not a number\n"); return -1; } else { while (src[n] && GDKisspace(src[n])) n++; **dst = (dbl) d; } } return n; }
ssize_t ptrFromStr(const char *src, size_t *len, ptr **dst, bool external) { size_t base = 0; const char *p = src; atommem(sizeof(ptr)); **dst = ptr_nil; if (GDK_STRNIL(src)) return 1; while (GDKisspace(*p)) p++; if (external && strncmp(p, "nil", 3) == 0) { p += 3; } else { if (p[0] == '0' && (p[1] == 'x' || p[1] == 'X')) { p += 2; } if (!num16(*p)) { GDKerror("not a number\n"); return -1; } while (num16(*p)) { if (base >= ((size_t) 1 << (8 * sizeof(size_t) - 4))) { GDKerror("overflow\n"); return -1; } base = mult16(base) + base16(*p); p++; } **dst = (ptr) base; } while (GDKisspace(*p)) p++; return (ssize_t) (p - src); }
int color_fromstr(char *colorStr, int *len, color **c) { char *p = colorStr; #ifdef DEBUG_COLOR printf("* color_fromstr:\n"); printf(" - colorStr: %s\n", (colorStr != NULL ? colorStr : "null")); printf(" - *len: %d\n", *len); #endif if (!*c) { *c = (color *) GDKmalloc(sizeof(color)); } else if (*len < (int) sizeof(color)) { GDKfree(*c); *c = GDKmalloc(sizeof(color)); *len = sizeof(color); } while (GDKisspace(*p)) p++; if (p[0] == 'n' && p[1] == 'i' && p[2] == 'l') { color **sc = (color **) c; **sc = color_nil; p += 3; } else { if (p[0] == '0' && p[1] == 'x' && p[2] == '0' && p[3] == '0') { int r = CLRhextoint(p[4], p[5]); int g = CLRhextoint(p[6], p[7]); int b = CLRhextoint(p[8], p[9]); **c = (color) (r << 16 | g << 8 | b); } else **c = color_nil; } #ifdef DEBUG_COLOR printf(" = *c: 0x%08X\n", (int) **c); printf(" = *len: %d\n", *len); #endif return (int) (p - colorStr); }
ssize_t batFromStr(const char *src, size_t *len, bat **dst, bool external) { char *s; const char *t, *r = src; int c; bat bid = 0; atommem(sizeof(bat)); if (GDK_STRNIL(src)) { **dst = bat_nil; return 1; } while (GDKisspace(*r)) r++; if (external && strcmp(r, "nil") == 0) { **dst = bat_nil; return (ssize_t) (r - src) + 3; } if (*r == '<') r++; t = r; while ((c = *t) && (c == '_' || GDKisalnum(c))) t++; s = GDKstrndup(r, t - r); if (s == NULL) return -1; bid = BBPindex(s); GDKfree(s); **dst = bid == 0 ? bat_nil : bid; return (ssize_t) (t + (c == '>') - src); }
static ssize_t numFromStr(const char *src, size_t *len, void **dst, int tp, bool external) { const char *p = src; size_t sz = ATOMsize(tp); #ifdef HAVE_HGE hge base = 0; #else lng base = 0; #endif int sign = 1; /* a valid number has the following syntax: * [-+]?[0-9]+([eE][0-9]+)?(LL)? -- PCRE syntax, or in other words * optional sign, one or more digits, optional exponent, optional LL * the exponent has the following syntax: * lower or upper case letter E, one or more digits * embedded spaces are not allowed * the optional LL at the end are only allowed for lng and hge * values */ atommem(sz); if (GDK_STRNIL(src)) { memcpy(*dst, ATOMnilptr(tp), sz); return 1; } while (GDKisspace(*p)) p++; if (!num10(*p)) { switch (*p) { case 'n': if (external) { memcpy(*dst, ATOMnilptr(tp), sz); if (p[1] == 'i' && p[2] == 'l') { p += 3; return (ssize_t) (p - src); } } GDKerror("not a number"); goto bailout; case '-': sign = -1; p++; break; case '+': p++; break; } if (!num10(*p)) { GDKerror("not a number"); goto bailout; } } do { int dig = base10(*p); if (base > maxdiv[1].maxval || (base == maxdiv[1].maxval && dig > maxmod10)) { /* overflow */ goto overflow; } base = 10 * base + dig; p++; } while (num10(*p)); if ((*p == 'e' || *p == 'E') && num10(p[1])) { p++; if (base == 0) { /* if base is 0, any exponent will do, the * result is still 0 */ while (num10(*p)) p++; } else { int exp = 0; do { /* this calculation cannot overflow */ exp = exp * 10 + base10(*p); if (exp >= (int) (sizeof(maxdiv) / sizeof(maxdiv[0]))) { /* overflow */ goto overflow; } p++; } while (num10(*p)); if (base > maxdiv[exp].maxval) { /* overflow */ goto overflow; } base *= maxdiv[exp].scale; } } base *= sign; switch (sz) { case 1: { bte **dstbte = (bte **) dst; if (base < GDK_bte_min || base > GDK_bte_max) { goto overflow; } **dstbte = (bte) base; break; } case 2: { sht **dstsht = (sht **) dst; if (base < GDK_sht_min || base > GDK_sht_max) { goto overflow; } **dstsht = (sht) base; break; } case 4: { int **dstint = (int **) dst; if (base < GDK_int_min || base > GDK_int_max) { goto overflow; } **dstint = (int) base; break; } case 8: { lng **dstlng = (lng **) dst; #ifdef HAVE_HGE if (base < GDK_lng_min || base > GDK_lng_max) { goto overflow; } #endif **dstlng = (lng) base; if (p[0] == 'L' && p[1] == 'L') p += 2; break; } #ifdef HAVE_HGE case 16: { hge **dsthge = (hge **) dst; **dsthge = (hge) base; if (p[0] == 'L' && p[1] == 'L') p += 2; break; } #endif } while (GDKisspace(*p)) p++; return (ssize_t) (p - src); overflow: while (num10(*p)) p++; GDKerror("overflow: \"%.*s\" does not fit in %s\n", (int) (p - src), src, ATOMname(tp)); bailout: memcpy(*dst, ATOMnilptr(tp), sz); return -1; }