[svn.haxx.se] · SVN Dev · SVN Users · SVN Org · TSVN Dev · TSVN Users · Subclipse Dev · Subclipse Users · this month's index

Re: svn commit: r993183 - in /subversion/trunk/subversion: include/ libsvn_diff/ libsvn_ra_serf/ libsvn_subr/ mod_dav_svn/reports/

From: Julian Foad <julian.foad_at_wandisco.com>
Date: Wed, 15 Sep 2010 14:14:36 +0100

On Tue, 2010-09-07, stsp_at_apache.org wrote:
> Author: stsp
> Date: Tue Sep 7 00:09:46 2010
> New Revision: 993183
>
> URL: http://svn.apache.org/viewvc?rev=993183&view=rev
> Log:
> Introduce a new family of functions to parse numbers from strings.

Looks useful. Thanks.

> The goal is to replace direct calls to functions like atoi() and apr_atoi64(),
> which have very inconvenient error handling to the point where a lot of
> our code simply ignores conversion errors and continues operating with
> the converted data in potentially undefined state.
> The new functions, on the other hand, report conversion errors via the
> standard Subversion error handling interface, thereby not allowing callers
> to ignore conversion errors.
>
> This commit also switches selected pieces of code over to the new functions.
> More conversion to come.
>
> * subversion/include/svn_string.h
> (svn_cstring_strtoi64, svn_cstring_atoi64, svn_cstring_atoi,
> svn_cstring_strtoui64, svn_cstring_atoui64, svn_cstring_atoui): Declare.
>
> * subversion/libsvn_subr/svn_string.c
> (): Include svn_private_config.h for the _() gettext macro.
> (svn_cstring_strtoi64, svn_cstring_strtoui64, svn_cstring_atoi64,
> svn_cstring_atoi): New.

And the other two functions as well? (Just missing from the log
message.)

> * subversion/libsvn_ra_serf/serf.c
> (dirent_walker): Use svn_cstring_atoi64() instead of apr_atoi64().
>
> * subversion/libsvn_diff/parse-diff.c
> (parse_offset): Call svn_cstring_strtoui64() instead of calling
> apr_atoi64() and performing manual overflow checking.
>
> * subversion/mod_dav_svn/reports/log.c
> (dav_svn__log_report): Use svn_cstring_atoi() instead of atoi() for
> parsing CDATA of the "limit" element.
>
> * subversion/mod_dav_svn/reports/replay.c
> (dav_svn__replay_report): Use svn_cstring_strtoi64() instead of atoi() for
> parsing CDATA of the "send-deltas" element.
>
> * subversion/libsvn_subr/win32_xlate.c
> (get_page_id_from_name): Use svn_cstring_atoui() instead of atoi() to parse
> the number of a codepage.
>
> * subversion/libsvn_subr/io.c
> (svn_io_read_version_file): Use svn_cstring_atoi() instead of atoi().
>
> * subversion/libsvn_subr/hash.c
> (svn_hash_read): Use svn_cstring_atoi() instead of atoi().

> Modified: subversion/trunk/subversion/include/svn_string.h
> +/**
> + * Parse the C string @a str into a 64 bit number, and return it in @a *n.
> + * Assume that the number is represented in base @a base.
> + * Raise an error if conversion fails (e.g. due to overflow), or if the
> + * converted number is smaller than @a minval or larger than @a maxval.

What are the semantics regarding 'str' - does it ignore leading spaces,
a plus sign, decimal point, trailing spaces, trailing non-spaces?
Preferably refer to a standard function to make this clear without
trying to spell it all out in full.

> + * @since New in 1.7.
> + */
> +svn_error_t *
> +svn_cstring_strtoi64(apr_int64_t *n, const char *str,
> + apr_int64_t minval, apr_int64_t maxval,
> + int base);
> +
> +/**
> + * Parse the C string @a str into a 64 bit number, and return it in @a *n.
> + * Assume that the number is represented in base 10.
> + * Raise an error if conversion fails (e.g. due to overflow).
> + *
> + * @since New in 1.7.
> + */
> +svn_error_t *
> +svn_cstring_atoi64(apr_int64_t *n, const char *str);
> +
> +/**
> + * Parse the C string @a str into a 32 bit number, and return it in @a *n.

What does "parse into a 32 bit number" mean when 'int' is not 32 bits?

If the intention is to limit this to 32-bit numbers its name should
reflect it. (The data type *could* stay as 'int' because we are allowed
to assume it's at least 32 bits, but I don't know if we'd want to do
that.)

Otherwise it should support the range of 'int' and not assume 32 bits.

> + * Assume that the number is represented in base 10.
> + * Raise an error if conversion fails (e.g. due to overflow).
> + *
> + * @since New in 1.7.
> + */
> +svn_error_t *
> +svn_cstring_atoi(int *n, const char *str);
> +
> +/**
> + * Parse the C string @a str into an unsigned 64 bit number, and return
> + * it in @a *n. Assume that the number is represented in base @a base.
> + * Raise an error if conversion fails (e.g. due to overflow), or if the
> + * converted number is smaller than @a minval or larger than @a maxval.
> + *
> + * @since New in 1.7.
> + */
> +svn_error_t *
> +svn_cstring_strtoui64(apr_uint64_t *n, const char *str,
> + apr_uint64_t minval, apr_uint64_t maxval,
> + int base);
> +
> +/**
> + * Parse the C string @a str into an unsigned 64 bit number, and return
> + * it in @a *n. Assume that the number is represented in base 10.
> + * Raise an error if conversion fails (e.g. due to overflow).
> + *
> + * @since New in 1.7.
> + */
> +svn_error_t *
> +svn_cstring_atoui64(apr_uint64_t *n, const char *str);
> +
> +/**
> + * Parse the C string @a str into an unsigned 32 bit number, and return
> + * it in @a *n. Assume that the number is represented in base 10.
> + * Raise an error if conversion fails (e.g. due to overflow).
> + *
> + * @since New in 1.7.
> + */
> +svn_error_t *
> +svn_cstring_atoui(unsigned int *n, const char *str);

[...]
> Modified: subversion/trunk/subversion/libsvn_subr/svn_string.c
> +svn_error_t *
> +svn_cstring_strtoui64(apr_uint64_t *n, const char *str,
> + apr_uint64_t minval, apr_uint64_t maxval,
> + int base)
> +{
> + apr_int64_t parsed;
> +
> + /* We assume errno is thread-safe. */
> + errno = 0; /* APR-0.9 doesn't always set errno */
> +
> + /* ### We're throwing away half the number range here.
> + * ### Maybe implement our own number parser? */

What use is this function, compared to _strtoi64(), if it doesn't
actually support the top half of the range?

> + parsed = apr_strtoi64(str, NULL, base);
> + if (errno != 0)
> + return svn_error_return(
> + svn_error_createf(SVN_ERR_INCORRECT_PARAMS, NULL,
> + _("Could not convert '%s' into a number"),
> + str));
> + if (parsed < 0 || parsed < minval || parsed > maxval)

Forget "parsed < 0"; the "parsed < minval" term will always catch that
case because minval can't be negative.

> + return svn_error_return(
> + svn_error_createf(SVN_ERR_INCORRECT_PARAMS, NULL,
> + _("Number '%s' is out of range"), str));
> + *n = parsed;
> + return SVN_NO_ERROR;
> +}
> +
> +svn_error_t *
> +svn_cstring_atoui64(apr_uint64_t *n, const char *str)
> +{
> + return svn_error_return(svn_cstring_strtoui64(n, str, 0,
> + APR_UINT64_MAX, 10));
> +}
> +
> +svn_error_t *
> +svn_cstring_atoui(unsigned int *n, const char *str)
> +{
> + apr_uint64_t parsed;
> +
> + SVN_ERR(svn_cstring_strtoui64(&parsed, str, 0, APR_UINT32_MAX, 10));

Inconsistent range limits - see above.

> + *n = (unsigned int)parsed;
> + return SVN_NO_ERROR;
> +}
> +
> +svn_error_t *
> +svn_cstring_strtoi64(apr_int64_t *n, const char *str,
> + apr_int64_t minval, apr_int64_t maxval,
> + int base)
> +{
> + apr_int64_t parsed;
> +
> + /* We assume errno is thread-safe. */
> + errno = 0; /* APR-0.9 doesn't always set errno */
> +
> + parsed = apr_strtoi64(str, NULL, base);
> + if (errno != 0)
> + return svn_error_return(
> + svn_error_createf(SVN_ERR_INCORRECT_PARAMS, NULL,
> + _("Could not convert '%s' into a number"),
> + str));
> + if (parsed < minval || parsed > maxval)
> + return svn_error_return(
> + svn_error_createf(SVN_ERR_INCORRECT_PARAMS, NULL,
> + _("Number '%s' is out of range"), str));
> + *n = parsed;
> + return SVN_NO_ERROR;
> +}

Nice.

> +
> +svn_error_t *
> +svn_cstring_atoi64(apr_int64_t *n, const char *str)
> +{
> + return svn_error_return(svn_cstring_strtoi64(n, str, APR_INT64_MIN,
> + APR_INT64_MAX, 10));
> +}
> +
> +svn_error_t *
> +svn_cstring_atoi(int *n, const char *str)
> +{
> + apr_int64_t parsed;
> +
> + SVN_ERR(svn_cstring_strtoi64(&parsed, str, APR_INT32_MIN,
> + APR_INT32_MAX, 10));

Inconsistent range limits - see above.

> + *n = (int)parsed;
> + return SVN_NO_ERROR;
> +}

- Julian
Received on 2010-09-15 15:23:30 CEST

This is an archived mail posted to the Subversion Dev mailing list.