Rev 2487: Now that we have bisect_dirblock working again, bring back cmp_dirblock_strings. in http://bzr.arbash-meinel.com/branches/bzr/0.17-dev/dirstate_pyrex

John Arbash Meinel john at arbash-meinel.com
Fri May 4 16:50:27 BST 2007


At http://bzr.arbash-meinel.com/branches/bzr/0.17-dev/dirstate_pyrex

------------------------------------------------------------
revno: 2487
revision-id: john at arbash-meinel.com-20070504155015-l31mrfviixrrf277
parent: john at arbash-meinel.com-20070504154346-fgz2nrtwtd8u9w6a
committer: John Arbash Meinel <john at arbash-meinel.com>
branch nick: dirstate_pyrex
timestamp: Fri 2007-05-04 10:50:15 -0500
message:
  Now that we have bisect_dirblock working again, bring back cmp_dirblock_strings.
modified:
  bzrlib/compiled/dirstate_helpers.pyx dirstate_helpers.pyx-20070503201057-u425eni465q4idwn-3
-------------- next part --------------
=== modified file 'bzrlib/compiled/dirstate_helpers.pyx'
--- a/bzrlib/compiled/dirstate_helpers.pyx	2007-05-04 15:43:46 +0000
+++ b/bzrlib/compiled/dirstate_helpers.pyx	2007-05-04 15:50:15 +0000
@@ -22,6 +22,9 @@
 from bzrlib.dirstate import DirState
 
 
+cdef extern from *:
+    ctypedef int size_t
+
 cdef extern from "Python.h":
     # GetItem returns a borrowed reference
     void *PyDict_GetItem(object p, object key)
@@ -32,9 +35,17 @@
     int PyList_CheckExact(object)
     int PyTuple_CheckExact(object)
 
+    char *PyString_AsString(object p)
+    int PyString_Size(object p)
+
     void Py_INCREF(object)
     void Py_DECREF(object)
 
+cdef extern from "string.h":
+    int strncmp(char *s1, char *s2, size_t len)
+    int strcmp(char *s1, char *s2)
+    char *strchr(char *s1, char c)
+
 
 cdef object _split_from_path(object cache, object path):
     """get the dirblock tuple for a given path.
@@ -58,6 +69,82 @@
     return value
 
 
+cdef int _cmp_dirblock_strings(char *path1, int size1, char *path2, int size2):
+    """This compares 2 strings separating on path sections.
+
+    This is equivalent to "cmp(path1.split('/'), path2.split('/'))"
+    However, we don't want to create an extra object for doing the split.
+
+    :param path1: The first path to compare
+    :param size1: The length of the first path
+    :param path2: The second path
+    :param size1: The length of the second path
+    :return: 0 if they are equal, -1 if path1 comes first, 1 if path2 comes
+        first
+    """
+    cdef char *base1
+    cdef char *base2
+    cdef char *tip1
+    cdef char *tip2
+    cdef char *end1
+    cdef char *end2
+    cdef int cur_len1
+    cdef int cur_len2
+    cdef int cmp_len
+    cdef int diff
+
+    base1 = path1
+    base2 = path2
+    end1 = base1 + size1
+    end2 = base2 + size2
+
+    # Ensure that we are pointing to the final NULL terminator on both ends
+    assert end1[0] == c'\x00'
+    assert end2[0] == c'\x00'
+
+    while base1 < end1 and base2 < end2:
+        # Find the next path separator
+        # (This is where you would like strchrnul)
+        tip1 = strchr(base1, c'/')
+        tip2 = strchr(base2, c'/')
+
+        if tip1 == NULL:
+            tip1 = end1
+        if tip2 == NULL:
+            tip2 = end2
+
+        cur_len1 = tip1 - base1
+        cur_len2 = tip2 - base2
+        cmp_len = cur_len1
+        if cur_len2 < cur_len1:
+            cmp_len = cur_len2
+
+        diff = strncmp(base1, base2, cmp_len)
+        # print 'comparing "%s", "%s", %d = %d' % (base1, base2, cmp_len, diff)
+        if diff != 0:
+            return diff
+        if cur_len1 < cur_len2:
+            return -1
+        elif cur_len1 > cur_len2:
+            return 1
+        base1 = tip1+1
+        base2 = tip2+1
+    # Do we still have uncompared characters?
+    if base1 < end1:
+        return 1
+    if base2 < end2:
+        return -1
+    return 0
+
+
+def cmp_dirblock_strings(path1, path2):
+    """Compare to python strings in dirblock fashion."""
+    return _cmp_dirblock_strings(PyString_AsString(path1),
+                                 PyString_Size(path1),
+                                 PyString_AsString(path2),
+                                 PyString_Size(path2))
+
+
 def bisect_dirblock(dirblocks, dirname, lo=0, hi=None, cache={}):
     """Return the index where to insert dirname into the dirblocks.
 



More information about the bazaar-commits mailing list