mercurial/pathencode.c
author Adrian Buehlmann <adrian@cadifra.com>
Tue, 18 Sep 2012 11:43:30 +0200
changeset 17606 318fb32b980e
child 17616 9535a0dc41f2
permissions -rw-r--r--
pathencode: new C module with fast encodedir() function Not yet used (will be enabled in a later patch). This patch is a stripped down version of patches originally created by Bryan O'Sullivan <bryano@fb.com>
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
17606
318fb32b980e pathencode: new C module with fast encodedir() function
Adrian Buehlmann <adrian@cadifra.com>
parents:
diff changeset
     1
/*
318fb32b980e pathencode: new C module with fast encodedir() function
Adrian Buehlmann <adrian@cadifra.com>
parents:
diff changeset
     2
 pathencode.c - efficient path name encoding
318fb32b980e pathencode: new C module with fast encodedir() function
Adrian Buehlmann <adrian@cadifra.com>
parents:
diff changeset
     3
318fb32b980e pathencode: new C module with fast encodedir() function
Adrian Buehlmann <adrian@cadifra.com>
parents:
diff changeset
     4
 Copyright 2012 Facebook
318fb32b980e pathencode: new C module with fast encodedir() function
Adrian Buehlmann <adrian@cadifra.com>
parents:
diff changeset
     5
318fb32b980e pathencode: new C module with fast encodedir() function
Adrian Buehlmann <adrian@cadifra.com>
parents:
diff changeset
     6
 This software may be used and distributed according to the terms of
318fb32b980e pathencode: new C module with fast encodedir() function
Adrian Buehlmann <adrian@cadifra.com>
parents:
diff changeset
     7
 the GNU General Public License, incorporated herein by reference.
318fb32b980e pathencode: new C module with fast encodedir() function
Adrian Buehlmann <adrian@cadifra.com>
parents:
diff changeset
     8
*/
318fb32b980e pathencode: new C module with fast encodedir() function
Adrian Buehlmann <adrian@cadifra.com>
parents:
diff changeset
     9
318fb32b980e pathencode: new C module with fast encodedir() function
Adrian Buehlmann <adrian@cadifra.com>
parents:
diff changeset
    10
#include <Python.h>
318fb32b980e pathencode: new C module with fast encodedir() function
Adrian Buehlmann <adrian@cadifra.com>
parents:
diff changeset
    11
#include <assert.h>
318fb32b980e pathencode: new C module with fast encodedir() function
Adrian Buehlmann <adrian@cadifra.com>
parents:
diff changeset
    12
#include <ctype.h>
318fb32b980e pathencode: new C module with fast encodedir() function
Adrian Buehlmann <adrian@cadifra.com>
parents:
diff changeset
    13
#include <stdlib.h>
318fb32b980e pathencode: new C module with fast encodedir() function
Adrian Buehlmann <adrian@cadifra.com>
parents:
diff changeset
    14
#include <string.h>
318fb32b980e pathencode: new C module with fast encodedir() function
Adrian Buehlmann <adrian@cadifra.com>
parents:
diff changeset
    15
318fb32b980e pathencode: new C module with fast encodedir() function
Adrian Buehlmann <adrian@cadifra.com>
parents:
diff changeset
    16
#include "util.h"
318fb32b980e pathencode: new C module with fast encodedir() function
Adrian Buehlmann <adrian@cadifra.com>
parents:
diff changeset
    17
318fb32b980e pathencode: new C module with fast encodedir() function
Adrian Buehlmann <adrian@cadifra.com>
parents:
diff changeset
    18
/* state machine for dir-encoding */
318fb32b980e pathencode: new C module with fast encodedir() function
Adrian Buehlmann <adrian@cadifra.com>
parents:
diff changeset
    19
enum dir_state {
318fb32b980e pathencode: new C module with fast encodedir() function
Adrian Buehlmann <adrian@cadifra.com>
parents:
diff changeset
    20
	DDOT,
318fb32b980e pathencode: new C module with fast encodedir() function
Adrian Buehlmann <adrian@cadifra.com>
parents:
diff changeset
    21
	DH,
318fb32b980e pathencode: new C module with fast encodedir() function
Adrian Buehlmann <adrian@cadifra.com>
parents:
diff changeset
    22
	DHGDI,
318fb32b980e pathencode: new C module with fast encodedir() function
Adrian Buehlmann <adrian@cadifra.com>
parents:
diff changeset
    23
	DDEFAULT,
318fb32b980e pathencode: new C module with fast encodedir() function
Adrian Buehlmann <adrian@cadifra.com>
parents:
diff changeset
    24
};
318fb32b980e pathencode: new C module with fast encodedir() function
Adrian Buehlmann <adrian@cadifra.com>
parents:
diff changeset
    25
318fb32b980e pathencode: new C module with fast encodedir() function
Adrian Buehlmann <adrian@cadifra.com>
parents:
diff changeset
    26
static inline void charcopy(char *dest, Py_ssize_t *destlen, size_t destsize,
318fb32b980e pathencode: new C module with fast encodedir() function
Adrian Buehlmann <adrian@cadifra.com>
parents:
diff changeset
    27
                            char c)
318fb32b980e pathencode: new C module with fast encodedir() function
Adrian Buehlmann <adrian@cadifra.com>
parents:
diff changeset
    28
{
318fb32b980e pathencode: new C module with fast encodedir() function
Adrian Buehlmann <adrian@cadifra.com>
parents:
diff changeset
    29
	if (dest) {
318fb32b980e pathencode: new C module with fast encodedir() function
Adrian Buehlmann <adrian@cadifra.com>
parents:
diff changeset
    30
		assert(*destlen < destsize);
318fb32b980e pathencode: new C module with fast encodedir() function
Adrian Buehlmann <adrian@cadifra.com>
parents:
diff changeset
    31
		dest[*destlen] = c;
318fb32b980e pathencode: new C module with fast encodedir() function
Adrian Buehlmann <adrian@cadifra.com>
parents:
diff changeset
    32
	}
318fb32b980e pathencode: new C module with fast encodedir() function
Adrian Buehlmann <adrian@cadifra.com>
parents:
diff changeset
    33
	(*destlen)++;
318fb32b980e pathencode: new C module with fast encodedir() function
Adrian Buehlmann <adrian@cadifra.com>
parents:
diff changeset
    34
}
318fb32b980e pathencode: new C module with fast encodedir() function
Adrian Buehlmann <adrian@cadifra.com>
parents:
diff changeset
    35
318fb32b980e pathencode: new C module with fast encodedir() function
Adrian Buehlmann <adrian@cadifra.com>
parents:
diff changeset
    36
static inline void memcopy(char *dest, Py_ssize_t *destlen, size_t destsize,
318fb32b980e pathencode: new C module with fast encodedir() function
Adrian Buehlmann <adrian@cadifra.com>
parents:
diff changeset
    37
                           const void *src, Py_ssize_t len)
318fb32b980e pathencode: new C module with fast encodedir() function
Adrian Buehlmann <adrian@cadifra.com>
parents:
diff changeset
    38
{
318fb32b980e pathencode: new C module with fast encodedir() function
Adrian Buehlmann <adrian@cadifra.com>
parents:
diff changeset
    39
	if (dest) {
318fb32b980e pathencode: new C module with fast encodedir() function
Adrian Buehlmann <adrian@cadifra.com>
parents:
diff changeset
    40
		assert(*destlen + len < destsize);
318fb32b980e pathencode: new C module with fast encodedir() function
Adrian Buehlmann <adrian@cadifra.com>
parents:
diff changeset
    41
		memcpy((void *)&dest[*destlen], src, len);
318fb32b980e pathencode: new C module with fast encodedir() function
Adrian Buehlmann <adrian@cadifra.com>
parents:
diff changeset
    42
	}
318fb32b980e pathencode: new C module with fast encodedir() function
Adrian Buehlmann <adrian@cadifra.com>
parents:
diff changeset
    43
	*destlen += len;
318fb32b980e pathencode: new C module with fast encodedir() function
Adrian Buehlmann <adrian@cadifra.com>
parents:
diff changeset
    44
}
318fb32b980e pathencode: new C module with fast encodedir() function
Adrian Buehlmann <adrian@cadifra.com>
parents:
diff changeset
    45
318fb32b980e pathencode: new C module with fast encodedir() function
Adrian Buehlmann <adrian@cadifra.com>
parents:
diff changeset
    46
static Py_ssize_t _encodedir(char *dest, size_t destsize,
318fb32b980e pathencode: new C module with fast encodedir() function
Adrian Buehlmann <adrian@cadifra.com>
parents:
diff changeset
    47
                             const char *src, Py_ssize_t len)
318fb32b980e pathencode: new C module with fast encodedir() function
Adrian Buehlmann <adrian@cadifra.com>
parents:
diff changeset
    48
{
318fb32b980e pathencode: new C module with fast encodedir() function
Adrian Buehlmann <adrian@cadifra.com>
parents:
diff changeset
    49
	enum dir_state state = DDEFAULT;
318fb32b980e pathencode: new C module with fast encodedir() function
Adrian Buehlmann <adrian@cadifra.com>
parents:
diff changeset
    50
	Py_ssize_t i = 0, destlen = 0;
318fb32b980e pathencode: new C module with fast encodedir() function
Adrian Buehlmann <adrian@cadifra.com>
parents:
diff changeset
    51
318fb32b980e pathencode: new C module with fast encodedir() function
Adrian Buehlmann <adrian@cadifra.com>
parents:
diff changeset
    52
	while (i < len) {
318fb32b980e pathencode: new C module with fast encodedir() function
Adrian Buehlmann <adrian@cadifra.com>
parents:
diff changeset
    53
		switch (state) {
318fb32b980e pathencode: new C module with fast encodedir() function
Adrian Buehlmann <adrian@cadifra.com>
parents:
diff changeset
    54
		case DDOT:
318fb32b980e pathencode: new C module with fast encodedir() function
Adrian Buehlmann <adrian@cadifra.com>
parents:
diff changeset
    55
			switch (src[i]) {
318fb32b980e pathencode: new C module with fast encodedir() function
Adrian Buehlmann <adrian@cadifra.com>
parents:
diff changeset
    56
			case 'd':
318fb32b980e pathencode: new C module with fast encodedir() function
Adrian Buehlmann <adrian@cadifra.com>
parents:
diff changeset
    57
			case 'i':
318fb32b980e pathencode: new C module with fast encodedir() function
Adrian Buehlmann <adrian@cadifra.com>
parents:
diff changeset
    58
				state = DHGDI;
318fb32b980e pathencode: new C module with fast encodedir() function
Adrian Buehlmann <adrian@cadifra.com>
parents:
diff changeset
    59
				charcopy(dest, &destlen, destsize, src[i++]);
318fb32b980e pathencode: new C module with fast encodedir() function
Adrian Buehlmann <adrian@cadifra.com>
parents:
diff changeset
    60
				break;
318fb32b980e pathencode: new C module with fast encodedir() function
Adrian Buehlmann <adrian@cadifra.com>
parents:
diff changeset
    61
			case 'h':
318fb32b980e pathencode: new C module with fast encodedir() function
Adrian Buehlmann <adrian@cadifra.com>
parents:
diff changeset
    62
				state = DH;
318fb32b980e pathencode: new C module with fast encodedir() function
Adrian Buehlmann <adrian@cadifra.com>
parents:
diff changeset
    63
				charcopy(dest, &destlen, destsize, src[i++]);
318fb32b980e pathencode: new C module with fast encodedir() function
Adrian Buehlmann <adrian@cadifra.com>
parents:
diff changeset
    64
				break;
318fb32b980e pathencode: new C module with fast encodedir() function
Adrian Buehlmann <adrian@cadifra.com>
parents:
diff changeset
    65
			default:
318fb32b980e pathencode: new C module with fast encodedir() function
Adrian Buehlmann <adrian@cadifra.com>
parents:
diff changeset
    66
				state = DDEFAULT;
318fb32b980e pathencode: new C module with fast encodedir() function
Adrian Buehlmann <adrian@cadifra.com>
parents:
diff changeset
    67
				break;
318fb32b980e pathencode: new C module with fast encodedir() function
Adrian Buehlmann <adrian@cadifra.com>
parents:
diff changeset
    68
			}
318fb32b980e pathencode: new C module with fast encodedir() function
Adrian Buehlmann <adrian@cadifra.com>
parents:
diff changeset
    69
			break;
318fb32b980e pathencode: new C module with fast encodedir() function
Adrian Buehlmann <adrian@cadifra.com>
parents:
diff changeset
    70
		case DH:
318fb32b980e pathencode: new C module with fast encodedir() function
Adrian Buehlmann <adrian@cadifra.com>
parents:
diff changeset
    71
			if (src[i] == 'g') {
318fb32b980e pathencode: new C module with fast encodedir() function
Adrian Buehlmann <adrian@cadifra.com>
parents:
diff changeset
    72
				state = DHGDI;
318fb32b980e pathencode: new C module with fast encodedir() function
Adrian Buehlmann <adrian@cadifra.com>
parents:
diff changeset
    73
				charcopy(dest, &destlen, destsize, src[i++]);
318fb32b980e pathencode: new C module with fast encodedir() function
Adrian Buehlmann <adrian@cadifra.com>
parents:
diff changeset
    74
			}
318fb32b980e pathencode: new C module with fast encodedir() function
Adrian Buehlmann <adrian@cadifra.com>
parents:
diff changeset
    75
			else state = DDEFAULT;
318fb32b980e pathencode: new C module with fast encodedir() function
Adrian Buehlmann <adrian@cadifra.com>
parents:
diff changeset
    76
			break;
318fb32b980e pathencode: new C module with fast encodedir() function
Adrian Buehlmann <adrian@cadifra.com>
parents:
diff changeset
    77
		case DHGDI:
318fb32b980e pathencode: new C module with fast encodedir() function
Adrian Buehlmann <adrian@cadifra.com>
parents:
diff changeset
    78
			if (src[i] == '/') {
318fb32b980e pathencode: new C module with fast encodedir() function
Adrian Buehlmann <adrian@cadifra.com>
parents:
diff changeset
    79
				memcopy(dest, &destlen, destsize, ".hg", 3);
318fb32b980e pathencode: new C module with fast encodedir() function
Adrian Buehlmann <adrian@cadifra.com>
parents:
diff changeset
    80
				charcopy(dest, &destlen, destsize, src[i++]);
318fb32b980e pathencode: new C module with fast encodedir() function
Adrian Buehlmann <adrian@cadifra.com>
parents:
diff changeset
    81
			}
318fb32b980e pathencode: new C module with fast encodedir() function
Adrian Buehlmann <adrian@cadifra.com>
parents:
diff changeset
    82
			state = DDEFAULT;
318fb32b980e pathencode: new C module with fast encodedir() function
Adrian Buehlmann <adrian@cadifra.com>
parents:
diff changeset
    83
			break;
318fb32b980e pathencode: new C module with fast encodedir() function
Adrian Buehlmann <adrian@cadifra.com>
parents:
diff changeset
    84
		case DDEFAULT:
318fb32b980e pathencode: new C module with fast encodedir() function
Adrian Buehlmann <adrian@cadifra.com>
parents:
diff changeset
    85
			if (src[i] == '.')
318fb32b980e pathencode: new C module with fast encodedir() function
Adrian Buehlmann <adrian@cadifra.com>
parents:
diff changeset
    86
				state = DDOT;
318fb32b980e pathencode: new C module with fast encodedir() function
Adrian Buehlmann <adrian@cadifra.com>
parents:
diff changeset
    87
			charcopy(dest, &destlen, destsize, src[i++]);
318fb32b980e pathencode: new C module with fast encodedir() function
Adrian Buehlmann <adrian@cadifra.com>
parents:
diff changeset
    88
			break;
318fb32b980e pathencode: new C module with fast encodedir() function
Adrian Buehlmann <adrian@cadifra.com>
parents:
diff changeset
    89
		}
318fb32b980e pathencode: new C module with fast encodedir() function
Adrian Buehlmann <adrian@cadifra.com>
parents:
diff changeset
    90
	}
318fb32b980e pathencode: new C module with fast encodedir() function
Adrian Buehlmann <adrian@cadifra.com>
parents:
diff changeset
    91
318fb32b980e pathencode: new C module with fast encodedir() function
Adrian Buehlmann <adrian@cadifra.com>
parents:
diff changeset
    92
	return destlen;
318fb32b980e pathencode: new C module with fast encodedir() function
Adrian Buehlmann <adrian@cadifra.com>
parents:
diff changeset
    93
}
318fb32b980e pathencode: new C module with fast encodedir() function
Adrian Buehlmann <adrian@cadifra.com>
parents:
diff changeset
    94
318fb32b980e pathencode: new C module with fast encodedir() function
Adrian Buehlmann <adrian@cadifra.com>
parents:
diff changeset
    95
PyObject *encodedir(PyObject *self, PyObject *args)
318fb32b980e pathencode: new C module with fast encodedir() function
Adrian Buehlmann <adrian@cadifra.com>
parents:
diff changeset
    96
{
318fb32b980e pathencode: new C module with fast encodedir() function
Adrian Buehlmann <adrian@cadifra.com>
parents:
diff changeset
    97
	Py_ssize_t len, newlen;
318fb32b980e pathencode: new C module with fast encodedir() function
Adrian Buehlmann <adrian@cadifra.com>
parents:
diff changeset
    98
	PyObject *pathobj, *newobj;
318fb32b980e pathencode: new C module with fast encodedir() function
Adrian Buehlmann <adrian@cadifra.com>
parents:
diff changeset
    99
	char *path;
318fb32b980e pathencode: new C module with fast encodedir() function
Adrian Buehlmann <adrian@cadifra.com>
parents:
diff changeset
   100
318fb32b980e pathencode: new C module with fast encodedir() function
Adrian Buehlmann <adrian@cadifra.com>
parents:
diff changeset
   101
	if (!PyArg_ParseTuple(args, "O:encodedir", &pathobj))
318fb32b980e pathencode: new C module with fast encodedir() function
Adrian Buehlmann <adrian@cadifra.com>
parents:
diff changeset
   102
		return NULL;
318fb32b980e pathencode: new C module with fast encodedir() function
Adrian Buehlmann <adrian@cadifra.com>
parents:
diff changeset
   103
318fb32b980e pathencode: new C module with fast encodedir() function
Adrian Buehlmann <adrian@cadifra.com>
parents:
diff changeset
   104
	if (PyString_AsStringAndSize(pathobj, &path, &len) == -1) {
318fb32b980e pathencode: new C module with fast encodedir() function
Adrian Buehlmann <adrian@cadifra.com>
parents:
diff changeset
   105
		PyErr_SetString(PyExc_TypeError, "expected a string");
318fb32b980e pathencode: new C module with fast encodedir() function
Adrian Buehlmann <adrian@cadifra.com>
parents:
diff changeset
   106
		return NULL;
318fb32b980e pathencode: new C module with fast encodedir() function
Adrian Buehlmann <adrian@cadifra.com>
parents:
diff changeset
   107
	}
318fb32b980e pathencode: new C module with fast encodedir() function
Adrian Buehlmann <adrian@cadifra.com>
parents:
diff changeset
   108
318fb32b980e pathencode: new C module with fast encodedir() function
Adrian Buehlmann <adrian@cadifra.com>
parents:
diff changeset
   109
	newlen = len ? _encodedir(NULL, 0, path, len + 1) : 1;
318fb32b980e pathencode: new C module with fast encodedir() function
Adrian Buehlmann <adrian@cadifra.com>
parents:
diff changeset
   110
318fb32b980e pathencode: new C module with fast encodedir() function
Adrian Buehlmann <adrian@cadifra.com>
parents:
diff changeset
   111
	if (newlen == len + 1) {
318fb32b980e pathencode: new C module with fast encodedir() function
Adrian Buehlmann <adrian@cadifra.com>
parents:
diff changeset
   112
		Py_INCREF(pathobj);
318fb32b980e pathencode: new C module with fast encodedir() function
Adrian Buehlmann <adrian@cadifra.com>
parents:
diff changeset
   113
		return pathobj;
318fb32b980e pathencode: new C module with fast encodedir() function
Adrian Buehlmann <adrian@cadifra.com>
parents:
diff changeset
   114
	}
318fb32b980e pathencode: new C module with fast encodedir() function
Adrian Buehlmann <adrian@cadifra.com>
parents:
diff changeset
   115
318fb32b980e pathencode: new C module with fast encodedir() function
Adrian Buehlmann <adrian@cadifra.com>
parents:
diff changeset
   116
	newobj = PyString_FromStringAndSize(NULL, newlen);
318fb32b980e pathencode: new C module with fast encodedir() function
Adrian Buehlmann <adrian@cadifra.com>
parents:
diff changeset
   117
318fb32b980e pathencode: new C module with fast encodedir() function
Adrian Buehlmann <adrian@cadifra.com>
parents:
diff changeset
   118
	if (newobj) {
318fb32b980e pathencode: new C module with fast encodedir() function
Adrian Buehlmann <adrian@cadifra.com>
parents:
diff changeset
   119
		PyString_GET_SIZE(newobj)--;
318fb32b980e pathencode: new C module with fast encodedir() function
Adrian Buehlmann <adrian@cadifra.com>
parents:
diff changeset
   120
		_encodedir(PyString_AS_STRING(newobj), newlen, path,
318fb32b980e pathencode: new C module with fast encodedir() function
Adrian Buehlmann <adrian@cadifra.com>
parents:
diff changeset
   121
			   len + 1);
318fb32b980e pathencode: new C module with fast encodedir() function
Adrian Buehlmann <adrian@cadifra.com>
parents:
diff changeset
   122
	}
318fb32b980e pathencode: new C module with fast encodedir() function
Adrian Buehlmann <adrian@cadifra.com>
parents:
diff changeset
   123
318fb32b980e pathencode: new C module with fast encodedir() function
Adrian Buehlmann <adrian@cadifra.com>
parents:
diff changeset
   124
	return newobj;
318fb32b980e pathencode: new C module with fast encodedir() function
Adrian Buehlmann <adrian@cadifra.com>
parents:
diff changeset
   125
}