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/05/23 01:17:33 UTC

svn commit: r1485496 - /subversion/trunk/subversion/libsvn_subr/dirent_uri.c

Author: stefan2
Date: Wed May 22 23:17:32 2013
New Revision: 1485496

URL: http://svn.apache.org/r1485496
Log:
We frequently check relative paths for being canonical.  Speed that up
by minimizing the number of conditional jumps on the hot path.

* subversion/libsvn_subr/dirent_uri.c
  (relpath_is_canonical): minimize number of conditions in while() loop

Modified:
    subversion/trunk/subversion/libsvn_subr/dirent_uri.c

Modified: subversion/trunk/subversion/libsvn_subr/dirent_uri.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_subr/dirent_uri.c?rev=1485496&r1=1485495&r2=1485496&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_subr/dirent_uri.c (original)
+++ subversion/trunk/subversion/libsvn_subr/dirent_uri.c Wed May 22 23:17:32 2013
@@ -1688,7 +1688,8 @@ svn_dirent_is_canonical(const char *dire
 static svn_boolean_t
 relpath_is_canonical(const char *relpath)
 {
-  const char *ptr = relpath, *seg = relpath;
+  const char *ptr = relpath;
+  apr_size_t i, len;
 
   /* RELPATH is canonical if it has:
    *  - no '.' segments
@@ -1696,36 +1697,32 @@ relpath_is_canonical(const char *relpath
    *  - no '//'
    */
 
-  if (*relpath == '\0')
-    return TRUE;
-
+  /* invalid beginnings */
   if (*ptr == '/')
     return FALSE;
 
-  /* Now validate the rest of the path. */
-  while(1)
-    {
-      apr_size_t seglen = ptr - seg;
-
-      if (seglen == 1 && *seg == '.')
-        return FALSE;  /*  /./   */
-
-      if (*ptr == '/' && *(ptr+1) == '/')
-        return FALSE;  /*  //    */
-
-      if (! *ptr && *(ptr - 1) == '/')
-        return FALSE;  /* foo/  */
+  if (ptr[0] == '.' && (ptr[1] == '/' || ptr[1] == '\0'))
+    return FALSE;
 
-      if (! *ptr)
-        break;
+  /* valid special cases */
+  len = strlen(ptr);
+  if (len < 2)
+    return TRUE;
 
-      if (*ptr == '/')
-        ptr++;
-      seg = ptr;
+  /* invalid endings */
+  if (ptr[len-1] == '/' || (ptr[len-1] == '.' && ptr[len-2] == '/'))
+    return FALSE;
 
-      while (*ptr && (*ptr != '/'))
-        ptr++;
-    }
+  /* Now validate the rest of the path. */
+  for (i = 0; i < len - 1; ++i)
+    if (ptr[i] == '/' && ptr[i+1] <= '/') /* '.' and '/' have smaller UTF-8
+                                             codes than most other chars */
+      {
+        if (ptr[i+1] == '/')
+          return FALSE;  /*  //   */
+        if (ptr[i+1] == '.' && ptr[i+2] == '/')
+          return FALSE;  /*  /./  */
+      }
 
   return TRUE;
 }