Changeset: 7fc423e5191e for MonetDB URL: http://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=7fc423e5191e Modified Files: sql/backends/monet5/UDF/pyapi/Tests/pyapi_types_string.stable.out sql/backends/monet5/UDF/pyapi/type_conversion.c Branch: Dec2016 Log Message:
Code reuse and code deduplication. Added benefit: closer to correctness, so also approved test. diffs (truncated from 359 to 300 lines): diff --git a/sql/backends/monet5/UDF/pyapi/Tests/pyapi_types_string.stable.out b/sql/backends/monet5/UDF/pyapi/Tests/pyapi_types_string.stable.out --- a/sql/backends/monet5/UDF/pyapi/Tests/pyapi_types_string.stable.out +++ b/sql/backends/monet5/UDF/pyapi/Tests/pyapi_types_string.stable.out @@ -180,8 +180,8 @@ Ready. #--------------------------# [ 0@0, 18042.895 ] [ 1@0, 846.9309 ] -[ 2@0, 16.816929 ] -[ 3@0, 1714637 ] +[ 2@0, 16.816927 ] +[ 3@0, 1714636.9 ] [ 4@0, nil ] #io.print(rstr); #--------------------------# diff --git a/sql/backends/monet5/UDF/pyapi/type_conversion.c b/sql/backends/monet5/UDF/pyapi/type_conversion.c --- a/sql/backends/monet5/UDF/pyapi/type_conversion.c +++ b/sql/backends/monet5/UDF/pyapi/type_conversion.c @@ -25,7 +25,7 @@ bool string_copy(char * source, char* de { dest[i] = source[i]; if (dest[i] == 0) return TRUE; - if (!allow_unicode && (*(unsigned char*)&source[i]) >= 128) return FALSE; + if (!allow_unicode && source[i] & 0x80) return FALSE; } dest[max_size] = '\0'; return TRUE; @@ -34,40 +34,9 @@ bool string_copy(char * source, char* de #ifdef HAVE_HGE int hge_to_string(char * str, hge x) { - int i = 0; - size_t size = 1; - hge cpy = x > 0 ? x : -x; - while(cpy > 0) { - cpy /= 10; - size++; - } - if (x < 0) size++; - if (x < 0) - { - x *= -1; - str[0] = '-'; - } - str[size - 1] = '\0'; - i = size - 1; - while(x > 0) - { - int v = x % 10; - i--; - if (i < 0) return FALSE; - if (v == 0) str[i] = '0'; - else if (v == 1) str[i] = '1'; - else if (v == 2) str[i] = '2'; - else if (v == 3) str[i] = '3'; - else if (v == 4) str[i] = '4'; - else if (v == 5) str[i] = '5'; - else if (v == 6) str[i] = '6'; - else if (v == 7) str[i] = '7'; - else if (v == 8) str[i] = '8'; - else if (v == 9) str[i] = '9'; - x = x / 10; - } - - return TRUE; + int len = 256; /* assume str is large enough */ + hgeToStr(&str, &len, &x); + return TRUE; } PyObject *PyLong_FromHge(hge h) @@ -174,85 +143,121 @@ wrapup: return msg; } +#define STRING_TO_NUMBER_FACTORY(tpe) \ +str str_to_##tpe(char *ptr, size_t maxsize, tpe *value) \ +{ \ + int len = sizeof(tpe); \ + char buf[256]; \ + if (maxsize > 0) { \ + if (maxsize >= sizeof(buf)) \ + maxsize = sizeof(buf) - 1; \ + strncpy(buf, ptr, maxsize); \ + buf[maxsize] = 0; \ + if (strlen(buf) >= sizeof(buf) - 1) \ + return GDKstrdup("string too long to convert."); \ + ptr = buf; \ + } \ + if (BATatoms[TYPE_##tpe].atomFromStr(ptr, &len, (void **) &value) == 0) \ + return GDKstrdup("Error converting string."); \ + return MAL_SUCCEED; \ +} + #ifndef IS_PY3K -#define PY_TO_(type, inttpe) \ -str pyobject_to_##type(PyObject **pyobj, size_t maxsize, type *value) \ -{ \ - PyObject *ptr = *pyobj; \ - str retval = MAL_SUCCEED; \ - (void) maxsize; \ - if (PyLong_CheckExact(ptr)) { \ - PyLongObject *p = (PyLongObject*) ptr; \ - inttpe h = 0; \ - inttpe prev = 0; \ - ssize_t i = Py_SIZE(p); \ - int sign = i < 0 ? -1 : 1; \ - i *= sign; \ - while (--i >= 0) { \ - prev = h; (void)prev; \ - h = (h << PyLong_SHIFT) + p->ob_digit[i]; \ - if ((h >> PyLong_SHIFT) != prev) { \ - return GDKstrdup("Overflow when converting value."); \ - } \ - } \ - *value = (type)(h * sign); \ - } else if (PyInt_CheckExact(ptr) || PyBool_Check(ptr)) { \ - *value = (type)((PyIntObject*)ptr)->ob_ival; \ - } else if (PyFloat_CheckExact(ptr)) { \ - *value = (type) ((PyFloatObject*)ptr)->ob_fval; \ - } else if (PyString_CheckExact(ptr)) { \ - return str_to_##type(((PyStringObject*)ptr)->ob_sval, -1, value); \ - } else if (PyByteArray_CheckExact(ptr)) { \ - return str_to_##type(((PyByteArrayObject*)ptr)->ob_bytes, -1, value); \ - } else if (PyUnicode_CheckExact(ptr)) { \ - return unicode_to_##type(((PyUnicodeObject*)ptr)->str, -1, value); \ - } else if (ptr == Py_None) { \ - *value = type##_nil; \ - } \ - return retval; \ +#define PY_TO_(type, inttpe) \ +str pyobject_to_##type(PyObject **pyobj, size_t maxsize, type *value) \ +{ \ + PyObject *ptr = *pyobj; \ + str retval = MAL_SUCCEED; \ + (void) maxsize; \ + if (PyLong_CheckExact(ptr)) { \ + PyLongObject *p = (PyLongObject*) ptr; \ + inttpe h = 0; \ + inttpe prev = 0; \ + ssize_t i = Py_SIZE(p); \ + int sign = i < 0 ? -1 : 1; \ + i *= sign; \ + while (--i >= 0) { \ + prev = h; (void)prev; \ + h = (h << PyLong_SHIFT) + p->ob_digit[i]; \ + if ((h >> PyLong_SHIFT) != prev) { \ + return GDKstrdup("Overflow when converting value."); \ + } \ + } \ + *value = (type)(h * sign); \ + } else if (PyInt_CheckExact(ptr) || PyBool_Check(ptr)) { \ + *value = (type)((PyIntObject*)ptr)->ob_ival; \ + } else if (PyFloat_CheckExact(ptr)) { \ + *value = (type) ((PyFloatObject*)ptr)->ob_fval; \ + } else if (PyString_CheckExact(ptr)) { \ + return str_to_##type(((PyStringObject*)ptr)->ob_sval, 0, value); \ + } else if (PyByteArray_CheckExact(ptr)) { \ + return str_to_##type(((PyByteArrayObject*)ptr)->ob_bytes, 0, value); \ + } else if (PyUnicode_CheckExact(ptr)) { \ + return unicode_to_##type(((PyUnicodeObject*)ptr)->str, 0, value); \ + } else if (ptr == Py_None) { \ + *value = type##_nil; \ + } \ + return retval; \ } -#define CONVERSION_FUNCTION_FACTORY(tpe, inttpe) \ - str str_to_##tpe(char *ptr, size_t maxsize, tpe *value) \ - { \ - ssize_t i = maxsize - 1; \ - tpe factor = 1; \ - if (i < 0) i = strlen(ptr) - 1; \ - *value = 0; \ - for( ; i >= 0; i--) \ - { \ - switch(ptr[i]) \ - { \ - case '0': break; \ - case '1': *value += factor; break; \ - case '2': *value += 2 * factor; break; \ - case '3': *value += 3 * factor; break; \ - case '4': *value += 4 * factor; break; \ - case '5': *value += 5 * factor; break; \ - case '6': *value += 6 * factor; break; \ - case '7': *value += 7 * factor; break; \ - case '8': *value += 8 * factor; break; \ - case '9': *value += 9 * factor; break; \ - case '-': *value *= -1; break; \ - case '.': \ - case ',': *value /= factor; factor = 1; continue; \ - case '\0': continue; \ - default: \ - { \ - return GDKstrdup("Error converting string."); \ - } \ - } \ - factor *= 10; \ - } \ - return MAL_SUCCEED; \ - } \ - str unicode_to_##tpe(Py_UNICODE *ptr, size_t maxsize, tpe *value) \ - { \ - char utf8[255]; \ - unicode_to_utf8(0, 255, utf8, ptr); \ - return str_to_##tpe(utf8, maxsize, value); \ - } \ +#define CONVERSION_FUNCTION_FACTORY(tpe, inttpe) \ + STRING_TO_NUMBER_FACTORY(tpe) \ + str unicode_to_##tpe(Py_UNICODE *ptr, size_t maxsize, tpe *value) \ + { \ + char utf8[1024]; \ + if (maxsize == 0) \ + maxsize = utf32_strlen(ptr); \ + if (maxsize > 255) \ + maxsize = 255; \ + unicode_to_utf8(0, maxsize, utf8, ptr); \ + return str_to_##tpe(utf8, 0, value); \ + } \ PY_TO_(tpe, inttpe); +#else +#define PY_TO_(type, inttpe) \ +str pyobject_to_##type(PyObject **pyobj, size_t maxsize, type *value) \ +{ \ + PyObject *ptr = *pyobj; \ + str retval = MAL_SUCCEED; \ + (void) maxsize; \ + if (PyLong_CheckExact(ptr)) { \ + PyLongObject *p = (PyLongObject*) ptr; \ + inttpe h = 0; \ + inttpe prev = 0; \ + int i = Py_SIZE(p); \ + int sign = i < 0 ? -1 : 1; \ + i *= sign; \ + while (--i >= 0) { \ + prev = h; (void)prev; \ + h = (h << PyLong_SHIFT) + p->ob_digit[i]; \ + if ((h >> PyLong_SHIFT) != prev) { \ + return GDKstrdup("Overflow when converting value."); \ + } \ + } \ + *value = (type)(h * sign); \ + } else if (PyBool_Check(ptr)) { \ + *value = ptr == Py_True ? 1 : 0; \ + } else if (PyFloat_CheckExact(ptr)) { \ + *value = (type) ((PyFloatObject*)ptr)->ob_fval; \ + } else if (PyUnicode_CheckExact(ptr)) { \ + return str_to_##type(PyUnicode_AsUTF8(ptr), 0, value); \ + } else if (PyByteArray_CheckExact(ptr)) { \ + return str_to_##type(((PyByteArrayObject*)ptr)->ob_bytes, 0, value); \ + } else if (ptr == Py_None) { \ + *value = type##_nil; \ + } \ + return retval; \ +} +#define CONVERSION_FUNCTION_FACTORY(tpe, inttpe) \ + STRING_TO_NUMBER_FACTORY(tpe) \ + str unicode_to_##tpe(char *ptr, size_t maxsize, tpe *value) \ + { \ + return str_to_##tpe(ptr, maxsize, value); \ + } \ + PY_TO_(tpe, inttpe); + +#endif + CONVERSION_FUNCTION_FACTORY(bte, bte) CONVERSION_FUNCTION_FACTORY(oid, oid) CONVERSION_FUNCTION_FACTORY(bit, bit) @@ -267,91 +272,6 @@ CONVERSION_FUNCTION_FACTORY(dbl, hge) #else CONVERSION_FUNCTION_FACTORY(dbl, lng) #endif -#else -#define PY_TO_(type, inttpe) \ -str pyobject_to_##type(PyObject **pyobj, size_t maxsize, type *value) \ -{ \ - PyObject *ptr = *pyobj; \ - str retval = MAL_SUCCEED; \ - (void) maxsize; \ - if (PyLong_CheckExact(ptr)) { \ - PyLongObject *p = (PyLongObject*) ptr; \ - inttpe h = 0; \ - inttpe prev = 0; \ - int i = Py_SIZE(p); \ - int sign = i < 0 ? -1 : 1; \ - i *= sign; \ - while (--i >= 0) { \ - prev = h; (void)prev; \ - h = (h << PyLong_SHIFT) + p->ob_digit[i]; \ - if ((h >> PyLong_SHIFT) != prev) { \ - return GDKstrdup("Overflow when converting value."); \ - } \ - } \ - *value = (type)(h * sign); \ - } else if (PyBool_Check(ptr)) { \ - *value = ptr == Py_True ? 1 : 0; \ - } else if (PyFloat_CheckExact(ptr)) { \ - *value = (type) ((PyFloatObject*)ptr)->ob_fval; \ - } else if (PyUnicode_CheckExact(ptr)) { \ - return str_to_##type(PyUnicode_AsUTF8(ptr), -1, value); \ - } else if (PyByteArray_CheckExact(ptr)) { \ _______________________________________________ checkin-list mailing list checkin-list@monetdb.org https://www.monetdb.org/mailman/listinfo/checkin-list