mercurial/cext/charencode.c
changeset 36225 6c87d4113a90
parent 36058 81199632fa42
child 36620 186c6df3a373
equal deleted inserted replaced
36224:d0a3fa849cb8 36225:6c87d4113a90
   149 			Py_RETURN_FALSE;
   149 			Py_RETURN_FALSE;
   150 	}
   150 	}
   151 	Py_RETURN_TRUE;
   151 	Py_RETURN_TRUE;
   152 }
   152 }
   153 
   153 
   154 static inline PyObject *_asciitransform(PyObject *str_obj,
   154 static inline PyObject *
   155 					const char table[128],
   155 _asciitransform(PyObject *str_obj, const char table[128], PyObject *fallback_fn)
   156 					PyObject *fallback_fn)
       
   157 {
   156 {
   158 	char *str, *newstr;
   157 	char *str, *newstr;
   159 	Py_ssize_t i, len;
   158 	Py_ssize_t i, len;
   160 	PyObject *newobj = NULL;
   159 	PyObject *newobj = NULL;
   161 	PyObject *ret = NULL;
   160 	PyObject *ret = NULL;
   171 
   170 
   172 	for (i = 0; i < len; i++) {
   171 	for (i = 0; i < len; i++) {
   173 		char c = str[i];
   172 		char c = str[i];
   174 		if (c & 0x80) {
   173 		if (c & 0x80) {
   175 			if (fallback_fn != NULL) {
   174 			if (fallback_fn != NULL) {
   176 				ret = PyObject_CallFunctionObjArgs(fallback_fn,
   175 				ret = PyObject_CallFunctionObjArgs(
   177 					str_obj, NULL);
   176 				    fallback_fn, str_obj, NULL);
   178 			} else {
   177 			} else {
   179 				PyObject *err = PyUnicodeDecodeError_Create(
   178 				PyObject *err = PyUnicodeDecodeError_Create(
   180 					"ascii", str, len, i, (i + 1),
   179 				    "ascii", str, len, i, (i + 1),
   181 					"unexpected code byte");
   180 				    "unexpected code byte");
   182 				PyErr_SetObject(PyExc_UnicodeDecodeError, err);
   181 				PyErr_SetObject(PyExc_UnicodeDecodeError, err);
   183 				Py_XDECREF(err);
   182 				Py_XDECREF(err);
   184 			}
   183 			}
   185 			goto quit;
   184 			goto quit;
   186 		}
   185 		}
   218 	PyObject *k, *v;
   217 	PyObject *k, *v;
   219 	dirstateTupleObject *tuple;
   218 	dirstateTupleObject *tuple;
   220 	Py_ssize_t pos = 0;
   219 	Py_ssize_t pos = 0;
   221 	const char *table;
   220 	const char *table;
   222 
   221 
   223 	if (!PyArg_ParseTuple(args, "O!O!O!:make_file_foldmap",
   222 	if (!PyArg_ParseTuple(args, "O!O!O!:make_file_foldmap", &PyDict_Type,
   224 			      &PyDict_Type, &dmap,
   223 	                      &dmap, &PyInt_Type, &spec_obj, &PyFunction_Type,
   225 			      &PyInt_Type, &spec_obj,
   224 	                      &normcase_fallback))
   226 			      &PyFunction_Type, &normcase_fallback))
       
   227 		goto quit;
   225 		goto quit;
   228 
   226 
   229 	spec = (int)PyInt_AS_LONG(spec_obj);
   227 	spec = (int)PyInt_AS_LONG(spec_obj);
   230 	switch (spec) {
   228 	switch (spec) {
   231 	case NORMCASE_LOWER:
   229 	case NORMCASE_LOWER:
   249 		goto quit;
   247 		goto quit;
   250 
   248 
   251 	while (PyDict_Next(dmap, &pos, &k, &v)) {
   249 	while (PyDict_Next(dmap, &pos, &k, &v)) {
   252 		if (!dirstate_tuple_check(v)) {
   250 		if (!dirstate_tuple_check(v)) {
   253 			PyErr_SetString(PyExc_TypeError,
   251 			PyErr_SetString(PyExc_TypeError,
   254 					"expected a dirstate tuple");
   252 			                "expected a dirstate tuple");
   255 			goto quit;
   253 			goto quit;
   256 		}
   254 		}
   257 
   255 
   258 		tuple = (dirstateTupleObject *)v;
   256 		tuple = (dirstateTupleObject *)v;
   259 		if (tuple->state != 'r') {
   257 		if (tuple->state != 'r') {
   260 			PyObject *normed;
   258 			PyObject *normed;
   261 			if (table != NULL) {
   259 			if (table != NULL) {
   262 				normed = _asciitransform(k, table,
   260 				normed = _asciitransform(k, table,
   263 					normcase_fallback);
   261 				                         normcase_fallback);
   264 			} else {
   262 			} else {
   265 				normed = PyObject_CallFunctionObjArgs(
   263 				normed = PyObject_CallFunctionObjArgs(
   266 					normcase_fallback, k, NULL);
   264 				    normcase_fallback, k, NULL);
   267 			}
   265 			}
   268 
   266 
   269 			if (normed == NULL)
   267 			if (normed == NULL)
   270 				goto quit;
   268 				goto quit;
   271 			if (PyDict_SetItem(file_foldmap, normed, k) == -1) {
   269 			if (PyDict_SetItem(file_foldmap, normed, k) == -1) {
   290 		/* don't want to process multi-byte escapes in C */
   288 		/* don't want to process multi-byte escapes in C */
   291 		for (i = 0; i < len; i++) {
   289 		for (i = 0; i < len; i++) {
   292 			char c = buf[i];
   290 			char c = buf[i];
   293 			if (c & 0x80) {
   291 			if (c & 0x80) {
   294 				PyErr_SetString(PyExc_ValueError,
   292 				PyErr_SetString(PyExc_ValueError,
   295 						"cannot process non-ascii str");
   293 				                "cannot process non-ascii str");
   296 				return -1;
   294 				return -1;
   297 			}
   295 			}
   298 			esclen += jsonparanoidlentable[(unsigned char)c];
   296 			esclen += jsonparanoidlentable[(unsigned char)c];
   299 			if (esclen < 0) {
   297 			if (esclen < 0) {
   300 				PyErr_SetString(PyExc_MemoryError,
   298 				PyErr_SetString(PyExc_MemoryError,
   301 						"overflow in jsonescapelen");
   299 				                "overflow in jsonescapelen");
   302 				return -1;
   300 				return -1;
   303 			}
   301 			}
   304 		}
   302 		}
   305 	} else {
   303 	} else {
   306 		for (i = 0; i < len; i++) {
   304 		for (i = 0; i < len; i++) {
   307 			char c = buf[i];
   305 			char c = buf[i];
   308 			esclen += jsonlentable[(unsigned char)c];
   306 			esclen += jsonlentable[(unsigned char)c];
   309 			if (esclen < 0) {
   307 			if (esclen < 0) {
   310 				PyErr_SetString(PyExc_MemoryError,
   308 				PyErr_SetString(PyExc_MemoryError,
   311 						"overflow in jsonescapelen");
   309 				                "overflow in jsonescapelen");
   312 				return -1;
   310 				return -1;
   313 			}
   311 			}
   314 		}
   312 		}
   315 	}
   313 	}
   316 
   314 
   334 	case '"':
   332 	case '"':
   335 		return '"';
   333 		return '"';
   336 	case '\\':
   334 	case '\\':
   337 		return '\\';
   335 		return '\\';
   338 	}
   336 	}
   339 	return '\0';  /* should not happen */
   337 	return '\0'; /* should not happen */
   340 }
   338 }
   341 
   339 
   342 /* convert 'origbuf' to JSON-escaped form 'escbuf'; 'origbuf' should only
   340 /* convert 'origbuf' to JSON-escaped form 'escbuf'; 'origbuf' should only
   343    include characters mappable by json(paranoid)lentable */
   341    include characters mappable by json(paranoid)lentable */
   344 static void encodejsonescape(char *escbuf, Py_ssize_t esclen,
   342 static void encodejsonescape(char *escbuf, Py_ssize_t esclen,
   345 			     const char *origbuf, Py_ssize_t origlen,
   343                              const char *origbuf, Py_ssize_t origlen,
   346 			     bool paranoid)
   344                              bool paranoid)
   347 {
   345 {
   348 	const uint8_t *lentable =
   346 	const uint8_t *lentable =
   349 		(paranoid) ? jsonparanoidlentable : jsonlentable;
   347 	    (paranoid) ? jsonparanoidlentable : jsonlentable;
   350 	Py_ssize_t i, j;
   348 	Py_ssize_t i, j;
   351 
   349 
   352 	for (i = 0, j = 0; i < origlen; i++) {
   350 	for (i = 0, j = 0; i < origlen; i++) {
   353 		char c = origbuf[i];
   351 		char c = origbuf[i];
   354 		uint8_t l = lentable[(unsigned char)c];
   352 		uint8_t l = lentable[(unsigned char)c];
   375 {
   373 {
   376 	PyObject *origstr, *escstr;
   374 	PyObject *origstr, *escstr;
   377 	const char *origbuf;
   375 	const char *origbuf;
   378 	Py_ssize_t origlen, esclen;
   376 	Py_ssize_t origlen, esclen;
   379 	int paranoid;
   377 	int paranoid;
   380 	if (!PyArg_ParseTuple(args, "O!i:jsonescapeu8fast",
   378 	if (!PyArg_ParseTuple(args, "O!i:jsonescapeu8fast", &PyBytes_Type,
   381 			      &PyBytes_Type, &origstr, &paranoid))
   379 	                      &origstr, &paranoid))
   382 		return NULL;
   380 		return NULL;
   383 
   381 
   384 	origbuf = PyBytes_AS_STRING(origstr);
   382 	origbuf = PyBytes_AS_STRING(origstr);
   385 	origlen = PyBytes_GET_SIZE(origstr);
   383 	origlen = PyBytes_GET_SIZE(origstr);
   386 	esclen = jsonescapelen(origbuf, origlen, paranoid);
   384 	esclen = jsonescapelen(origbuf, origlen, paranoid);
   387 	if (esclen < 0)
   385 	if (esclen < 0)
   388 		return NULL;  /* unsupported char found or overflow */
   386 		return NULL; /* unsupported char found or overflow */
   389 	if (origlen == esclen) {
   387 	if (origlen == esclen) {
   390 		Py_INCREF(origstr);
   388 		Py_INCREF(origstr);
   391 		return origstr;
   389 		return origstr;
   392 	}
   390 	}
   393 
   391 
   394 	escstr = PyBytes_FromStringAndSize(NULL, esclen);
   392 	escstr = PyBytes_FromStringAndSize(NULL, esclen);
   395 	if (!escstr)
   393 	if (!escstr)
   396 		return NULL;
   394 		return NULL;
   397 	encodejsonescape(PyBytes_AS_STRING(escstr), esclen, origbuf, origlen,
   395 	encodejsonescape(PyBytes_AS_STRING(escstr), esclen, origbuf, origlen,
   398 			 paranoid);
   396 	                 paranoid);
   399 
   397 
   400 	return escstr;
   398 	return escstr;
   401 }
   399 }