You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by st...@apache.org on 2013/07/20 00:03:35 UTC

svn commit: r1505046 - in /subversion/trunk: ./ subversion/include/private/svn_string_private.h subversion/libsvn_subr/string.c

Author: stefan2
Date: Fri Jul 19 22:03:34 2013
New Revision: 1505046

URL: http://svn.apache.org/r1505046
Log:
Merge revisions r1453590,1454307 from branches/fsfs-format7.
These introduce base36 conversion routines.

Modified:
    subversion/trunk/   (props changed)
    subversion/trunk/subversion/include/private/svn_string_private.h
    subversion/trunk/subversion/libsvn_subr/string.c

Propchange: subversion/trunk/
------------------------------------------------------------------------------
  Merged /subversion/branches/fsfs-format7:r1453590,1454307

Modified: subversion/trunk/subversion/include/private/svn_string_private.h
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/include/private/svn_string_private.h?rev=1505046&r1=1505045&r2=1505046&view=diff
==============================================================================
--- subversion/trunk/subversion/include/private/svn_string_private.h (original)
+++ subversion/trunk/subversion/include/private/svn_string_private.h Fri Jul 19 22:03:34 2013
@@ -175,6 +175,32 @@ svn__ui64toa_sep(apr_uint64_t number, ch
 char *
 svn__i64toa_sep(apr_int64_t number, char seperator, apr_pool_t *pool);
 
+
+/** Writes the @a number as base36-encoded string into @a dest. The latter
+ * must provide space for at least #SVN_INT64_BUFFER_SIZE characters.
+ * Returns the number chars written excluding the terminating NUL.
+ *
+ * @note The actual maximum buffer requirement is much shorter than
+ * #SVN_INT64_BUFFER_SIZE but introducing yet another constant is only
+ * marginally useful and may open the door to security issues when e.g.
+ * switching between base10 and base36 encoding.
+ */
+apr_size_t
+svn__ui64tobase36(char *dest, apr_uint64_t number);
+
+/** Returns the value of the base36 encoded unsigned integer starting at
+ * @a source.  If @a next is not NULL, @a *next will be set to the first
+ * position after the integer.
+ *
+ * The data in @a source will be considered part of the number to parse
+ * as long as the characters are within the base36 range.  If there are
+ * no such characters to begin with, 0 is returned.  Inputs with more than
+ * #SVN_INT64_BUFFER_SIZE digits will not be fully parsed, i.e. the value
+ * of @a *next as well as the return value are undefined.
+ */
+apr_uint64_t
+svn__base36toui64(const char **next, const char *source);
+
 /**
  * Computes the similarity score of STRA and STRB. Returns the ratio
  * of the length of their longest common subsequence and the average

Modified: subversion/trunk/subversion/libsvn_subr/string.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_subr/string.c?rev=1505046&r1=1505045&r2=1505046&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_subr/string.c (original)
+++ subversion/trunk/subversion/libsvn_subr/string.c Fri Jul 19 22:03:34 2013
@@ -1207,6 +1207,86 @@ svn__i64toa_sep(apr_int64_t number, char
   return apr_pstrdup(pool, buffer);
 }
 
+apr_size_t
+svn__ui64tobase36(char *dest, apr_uint64_t value)
+{
+  char *dest_start = dest;
+  if (value < 10)
+    {
+      /* pretty frequent and trivial case. Make it fast. */
+      *(dest++) = (char)(value) + '0';
+    }
+  else
+    {
+      char buffer[SVN_INT64_BUFFER_SIZE];
+      char *p = buffer;
+
+      /* write result as little-endian to buffer */
+      while (value > 0)
+        {
+          char c = (char)(value % 36);
+          value /= 36;
+
+          *p = (c <= 9) ? (c + '0') : (c - 10 + 'a');
+          ++p;
+        }
+
+      /* copy as big-endian to DEST */
+      while (p > buffer)
+        *(dest++) = *(--p);
+    }
+
+  *dest = '\0';
+  return dest - dest_start;
+}
+
+apr_uint64_t
+svn__base36toui64(const char **next, const char *source)
+{
+  apr_uint64_t result = 0;
+  apr_uint64_t factor = 1;
+  int i  = 0;
+  char digits[SVN_INT64_BUFFER_SIZE];
+
+  /* convert digits to numerical values and count the number of places.
+   * Also, prevent buffer overflow. */
+  while (i < sizeof(digits))
+    {
+      char c = *source;
+      if (c < 'a')
+        {
+          /* includes detection of NUL terminator */
+          if (c < '0' || c > '9')
+            break;
+
+          c -= '0';
+        }
+      else
+        {
+          if (c < 'a' || c > 'z')
+            break;
+
+          c -= 'a' - 10;
+        }
+
+      digits[i++] = c;
+      source++;
+    }
+
+  /* fold digits into the result */
+  while (i > 0)
+    {
+      result += factor * (apr_uint64_t)digits[--i];
+      factor *= 36;
+    }
+
+  if (next)
+    *next = source;
+
+  return result;
+}
+
+
 unsigned int
 svn_cstring__similarity(const char *stra, const char *strb,
                         svn_membuf_t *buffer, apr_size_t *rlcs)



Re: svn commit: r1505046 - in /subversion/trunk: ./ subversion/include/private/svn_string_private.h subversion/libsvn_subr/string.c

Posted by Ivan Zhakov <iv...@visualsvn.com>.
On Sat, Jul 20, 2013 at 2:03 AM,  <st...@apache.org> wrote:
> Author: stefan2
> Date: Fri Jul 19 22:03:34 2013
> New Revision: 1505046
>
> URL: http://svn.apache.org/r1505046
> Log:
> Merge revisions r1453590,1454307 from branches/fsfs-format7.
> These introduce base36 conversion routines.
>
> Modified:
>     subversion/trunk/   (props changed)
>     subversion/trunk/subversion/include/private/svn_string_private.h
>     subversion/trunk/subversion/libsvn_subr/string.c
>
> Propchange: subversion/trunk/
> ------------------------------------------------------------------------------
>   Merged /subversion/branches/fsfs-format7:r1453590,1454307
>
> Modified: subversion/trunk/subversion/include/private/svn_string_private.h
> URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/include/private/svn_string_private.h?rev=1505046&r1=1505045&r2=1505046&view=diff
> ==============================================================================
> --- subversion/trunk/subversion/include/private/svn_string_private.h (original)
> +++ subversion/trunk/subversion/include/private/svn_string_private.h Fri Jul 19 22:03:34 2013
> @@ -175,6 +175,32 @@ svn__ui64toa_sep(apr_uint64_t number, ch
>  char *
>  svn__i64toa_sep(apr_int64_t number, char seperator, apr_pool_t *pool);
>
> +
> +/** Writes the @a number as base36-encoded string into @a dest. The latter
> + * must provide space for at least #SVN_INT64_BUFFER_SIZE characters.
> + * Returns the number chars written excluding the terminating NUL.
> + *
> + * @note The actual maximum buffer requirement is much shorter than
> + * #SVN_INT64_BUFFER_SIZE but introducing yet another constant is only
> + * marginally useful and may open the door to security issues when e.g.
> + * switching between base10 and base36 encoding.
> + */
> +apr_size_t
> +svn__ui64tobase36(char *dest, apr_uint64_t number);
> +
> +/** Returns the value of the base36 encoded unsigned integer starting at
> + * @a source.  If @a next is not NULL, @a *next will be set to the first
> + * position after the integer.
> + *
> + * The data in @a source will be considered part of the number to parse
> + * as long as the characters are within the base36 range.  If there are
> + * no such characters to begin with, 0 is returned.  Inputs with more than
> + * #SVN_INT64_BUFFER_SIZE digits will not be fully parsed, i.e. the value
> + * of @a *next as well as the return value are undefined.
> + */
> +apr_uint64_t
> +svn__base36toui64(const char **next, const char *source);
> +
Hi Stefan,

Simple tests would be useful IMHO.



-- 
Ivan Zhakov