mercurial/cext/dirs.c
changeset 43229 9fa941faef94
parent 43149 2a0774e9d2a8
child 43232 be178b5d91c8
equal deleted inserted replaced
43228:0d609ed185ea 43229:9fa941faef94
    24  *
    24  *
    25  * A few implementation notes:
    25  * A few implementation notes:
    26  *
    26  *
    27  * We modify Python integers for refcounting, but those integers are
    27  * We modify Python integers for refcounting, but those integers are
    28  * never visible to Python code.
    28  * never visible to Python code.
    29  *
       
    30  * We mutate strings in-place, but leave them immutable once they can
       
    31  * be seen by Python code.
       
    32  */
    29  */
    33 typedef struct {
    30 typedef struct {
    34 	PyObject_HEAD
    31 	PyObject_HEAD
    35 	PyObject *dict;
    32 	PyObject *dict;
    36 } dirsObject;
    33 } dirsObject;
    61 	* The implementation, therefore, is heavily dependent on CPython
    58 	* The implementation, therefore, is heavily dependent on CPython
    62 	* implementation details. We also commit violations of the Python
    59 	* implementation details. We also commit violations of the Python
    63 	* "protocol" such as mutating immutable objects. But since we only
    60 	* "protocol" such as mutating immutable objects. But since we only
    64 	* mutate objects created in this function or in other well-defined
    61 	* mutate objects created in this function or in other well-defined
    65 	* locations, the references are known so these violations should go
    62 	* locations, the references are known so these violations should go
    66 	* unnoticed. The code for adjusting the length of a PyBytesObject is
    63 	* unnoticed. */
    67 	* essentially a minimal version of _PyBytes_Resize. */
       
    68 	while ((pos = _finddir(cpath, pos - 1)) != -1) {
    64 	while ((pos = _finddir(cpath, pos - 1)) != -1) {
    69 		PyObject *val;
    65 		PyObject *val;
    70 
    66 
    71 		if (pos < 2) {
    67 		key = PyBytes_FromStringAndSize(cpath, pos);
    72 			key = PyBytes_FromStringAndSize(cpath, pos);
    68 		if (key == NULL)
    73 			if (key == NULL)
    69 			goto bail;
    74 				goto bail;
       
    75 		} else {
       
    76 			/* It's likely that every prefix already has an entry
       
    77 			   in our dict. Try to avoid allocating and
       
    78 			   deallocating a string for each prefix we check. */
       
    79 			if (key != NULL)
       
    80 				((PyBytesObject *)key)->ob_shash = -1;
       
    81 			else {
       
    82 				/* We know pos >= 2, so we won't get a small
       
    83 				 * shared string. */
       
    84 				key = PyBytes_FromStringAndSize(cpath, pos);
       
    85 				if (key == NULL)
       
    86 					goto bail;
       
    87 			}
       
    88 			/* Py_SIZE(o) refers to the ob_size member of
       
    89 			 * the struct. Yes, assigning to what looks
       
    90 			 * like a function seems wrong. */
       
    91 			Py_SIZE(key) = pos;
       
    92 			((PyBytesObject *)key)->ob_sval[pos] = '\0';
       
    93 		}
       
    94 
    70 
    95 		val = PyDict_GetItem(dirs, key);
    71 		val = PyDict_GetItem(dirs, key);
    96 		if (val != NULL) {
    72 		if (val != NULL) {
    97 			PYLONG_VALUE(val) += 1;
    73 			PYLONG_VALUE(val) += 1;
    98 			if (pos < 2) {
    74 			Py_CLEAR(key);
    99 				/* This was a short string, so we
       
   100 				 * probably got a small shared string
       
   101 				 * we can't mutate on the next loop
       
   102 				 * iteration. Clear it.
       
   103 				 */
       
   104 				Py_CLEAR(key);
       
   105 			}
       
   106 			break;
    75 			break;
   107 		}
    76 		}
   108 
    77 
   109 		/* Force Python to not reuse a small shared int. */
    78 		/* Force Python to not reuse a small shared int. */
   110 #ifdef IS_PY3K
    79 #ifdef IS_PY3K