[Python-checkins] r54146 - sandbox/trunk/pep3101/unicodeformat.c
eric.smith
python-checkins at python.org
Tue Mar 6 05:04:01 CET 2007
Author: eric.smith
Date: Tue Mar 6 05:03:49 2007
New Revision: 54146
Modified:
sandbox/trunk/pep3101/unicodeformat.c
Log:
Refactored float formatting, again. This time it's simpler by using a callback, instead of the two-phase version I used last time.
Modified: sandbox/trunk/pep3101/unicodeformat.c
==============================================================================
--- sandbox/trunk/pep3101/unicodeformat.c (original)
+++ sandbox/trunk/pep3101/unicodeformat.c Tue Mar 6 05:03:49 2007
@@ -66,7 +66,6 @@
#define PySet_Discard PyDict_DelItem
#define PySet_New PyDict_Copy
#define PySet_GET_SIZE PyDict_Size
-#define PyOS_ascii_formatd PyOS_snprintf
#endif
@@ -1505,54 +1504,65 @@
return 1;
}
-/* state that needs to be passed between _format_float_phase1() and
- _format_float_phase2() */
-typedef struct {
+/* the callback function to call to do the actual float formatting.
+ it matches the definition of PyOS_ascii_formatd */
+typedef char*
+(*DoubleSnprintfFunction)(char *buffer, size_t buf_len,
+ const char *format, double d);
+
+/* just a wrapper to make PyOS_snprintf look like DoubleSnprintfFunction */
+static char*
+snprintf_double(char *buffer, size_t buf_len, const char *format, double d)
+{
+ PyOS_snprintf(buffer, buf_len, format, d);
+ return NULL;
+}
+
+/* use type instead of format->type, so that it can be overridden by
+ format_locale_number() */
+static int
+_format_float(CH_TYPE type, PyObject *fieldobj, FmtState *fs,
+ const InternalFormatSpec *format,
+ DoubleSnprintfFunction snprintf)
+{
/* fmt = '%.' + `prec` + `type` + '%%'
worst case length = 2 + 10 (len of INT_MAX) + 1 + 2 = 15 (use 20)*/
char fmt[20];
CH_TYPE *buf;
int buflen;
double x;
-} FloatState;
+ int len;
+ Py_ssize_t precision = format->precision;
+ char* trailing = "";
-/* use type instead of format->type, so that it can be overridden by
- format_locale_number() */
-static int
-_format_float_phase1(FloatState *state, CH_TYPE type, PyObject *fieldobj,
- FmtState *fs, const InternalFormatSpec *format)
-{
/* first, do the conversion as 8-bit chars, using the platform's
snprintf. then, if needed, convert to unicode. */
- Py_ssize_t precision = format->precision;
- char* trailing = "";
-
/* 'F' is the same as 'f', per the PEP */
if (type == 'F')
type = 'f';
- state->x = PyFloat_AsDouble(fieldobj);
- if (state->x == -1.0 && PyErr_Occurred()) {
+ x = PyFloat_AsDouble(fieldobj);
+ if (x == -1.0 && PyErr_Occurred()) {
printf("not a float\n");
return 0;
}
if (type == '%') {
type = 'f';
- state->x *= 100;
+ x *= 100;
trailing = "%%";
}
if (precision < 0)
precision = 6;
- if (type == 'f' && (fabs(state->x) / 1e25) >= 1e25)
+ if (type == 'f' && (fabs(x) / 1e25) >= 1e25)
type = 'g';
/* cast "type", because if we're in unicode we need to pass a
8-bit char. this is safe, because we've restricted what "type"
can be */
- PyOS_snprintf(state->fmt, sizeof(state->fmt), "%%.%d%c%s", precision,
+ PyOS_snprintf(fmt, sizeof(fmt), "%%.%d%c%s", precision,
(char)type, trailing);
/* this is taken from unicodeobject.c, except we don't force a
@@ -1576,30 +1586,24 @@
/* so, allocate the precision plus 54 chars (we add one additional
for the trailing percent). do this allocation as the native
type, because we're going to convert to unicode anyway */
- state->buflen = 54 + precision;
- if (output_allocate(fs, state->buflen, &state->buf) == 0)
+ buflen = 54 + precision;
+ if (output_allocate(fs, buflen, &buf) == 0)
return 0;
- return 1;
-}
-
-
-static int
-_format_float_phase2(FloatState *state, FmtState *fs)
-{
- int len;
+ /* call the passed in function to do the actual formatting */
+ snprintf((char*)buf, buflen, fmt, x);
#if C_UNICODE
- len = strtounicode(state->buf, (char*)state->buf, -1);
+ len = strtounicode(buf, (char*)buf, -1);
#else
/* compute the length. I believe this is done because the return
value from snprintf above is unreliable */
- len = strlen(state->buf);
+ len = strlen(buf);
#endif
/* shrink the buffer down to how many characters we actually
wrote. this is cheap, just pointer arithmetic */
- output_shrink(fs, state->buflen - len);
+ output_shrink(fs, buflen - len);
return 1;
}
@@ -1608,11 +1612,13 @@
format_float(PyObject *fieldobj, FmtState *fs,
const InternalFormatSpec *format)
{
- FloatState state;
- if (_format_float_phase1(&state, format->type, fieldobj, fs, format) == 0)
- return 0;
- PyOS_ascii_formatd((char *)state.buf, state.buflen, state.fmt, state.x);
- return _format_float_phase2(&state, fs);
+ return _format_float(format->type, fieldobj, fs, format,
+#if PYTHON_API_VERSION < 1013
+ snprintf_double
+#else
+ PyOS_ascii_formatd
+#endif
+ );
}
/* this code is really the same as format_exponent, except it calls
@@ -1621,12 +1627,7 @@
format_locale_number(PyObject *fieldobj, FmtState *fs,
const InternalFormatSpec *format)
{
- FloatState state;
- if (_format_float_phase1(&state, 'f', fieldobj, fs, format) == 0) {
- return 0;
- }
- PyOS_snprintf((char *)state.buf, state.buflen, state.fmt, state.x);
- return _format_float_phase2(&state, fs);
+ return _format_float('f', fieldobj, fs, format, snprintf_double);
}
static int
More information about the Python-checkins
mailing list