cinap_lenrekadd hg and python4bb9e2215 years agoHistory
8067 lines · 210.4 KB · C
RawDownload
    if (mapping->ob_type == &EncodingMapType) {        int res = encoding_map_lookup(c, mapping);	Py_ssize_t requiredsize = *outpos+1;        if (res == -1)            return enc_FAILED;	if (outsize<requiredsize) 	    if (!charmapencode_resize(outobj, outpos, requiredsize))		return enc_EXCEPTION;        outstart = PyString_AS_STRING(*outobj);	outstart[(*outpos)++] = (char)res;	return enc_SUCCESS;    }     rep = charmapencode_lookup(c, mapping);    if (rep==NULL)	return enc_EXCEPTION;    else if (rep==Py_None) {	Py_DECREF(rep);	return enc_FAILED;    } else {	if (PyInt_Check(rep)) {	    Py_ssize_t requiredsize = *outpos+1;	    if (outsize<requiredsize)		if (!charmapencode_resize(outobj, outpos, requiredsize)) {		    Py_DECREF(rep);		    return enc_EXCEPTION;		}            outstart = PyString_AS_STRING(*outobj);	    outstart[(*outpos)++] = (char)PyInt_AS_LONG(rep);	}	else {	    const char *repchars = PyString_AS_STRING(rep);	    Py_ssize_t repsize = PyString_GET_SIZE(rep);	    Py_ssize_t requiredsize = *outpos+repsize;	    if (outsize<requiredsize)		if (!charmapencode_resize(outobj, outpos, requiredsize)) {		    Py_DECREF(rep);		    return enc_EXCEPTION;		}            outstart = PyString_AS_STRING(*outobj);	    memcpy(outstart + *outpos, repchars, repsize);	    *outpos += repsize;	}    }    Py_DECREF(rep);    return enc_SUCCESS;} /* handle an error in PyUnicode_EncodeCharmap   Return 0 on success, -1 on error */staticint charmap_encoding_error(    const Py_UNICODE *p, Py_ssize_t size, Py_ssize_t *inpos, PyObject *mapping,    PyObject **exceptionObject,    int *known_errorHandler, PyObject **errorHandler, const char *errors,    PyObject **res, Py_ssize_t *respos){    PyObject *repunicode = NULL; /* initialize to prevent gcc warning */    Py_ssize_t repsize;    Py_ssize_t newpos;    Py_UNICODE *uni2;    /* startpos for collecting unencodable chars */    Py_ssize_t collstartpos = *inpos;    Py_ssize_t collendpos = *inpos+1;    Py_ssize_t collpos;    char *encoding = "charmap";    char *reason = "character maps to <undefined>";    charmapencode_result x;     /* find all unencodable characters */    while (collendpos < size) {        PyObject *rep;        if (mapping->ob_type == &EncodingMapType) {	    int res = encoding_map_lookup(p[collendpos], mapping);	    if (res != -1)		break;	    ++collendpos;	    continue;	}            	rep = charmapencode_lookup(p[collendpos], mapping);	if (rep==NULL)	    return -1;	else if (rep!=Py_None) {	    Py_DECREF(rep);	    break;	}	Py_DECREF(rep);	++collendpos;    }    /* cache callback name lookup     * (if not done yet, i.e. it's the first error) */    if (*known_errorHandler==-1) {	if ((errors==NULL) || (!strcmp(errors, "strict")))	    *known_errorHandler = 1;	else if (!strcmp(errors, "replace"))	    *known_errorHandler = 2;	else if (!strcmp(errors, "ignore"))	    *known_errorHandler = 3;	else if (!strcmp(errors, "xmlcharrefreplace"))	    *known_errorHandler = 4;	else	    *known_errorHandler = 0;    }    switch (*known_errorHandler) {	case 1: /* strict */	    raise_encode_exception(exceptionObject, encoding, p, size, collstartpos, collendpos, reason);	    return -1;	case 2: /* replace */	    for (collpos = collstartpos; collpos<collendpos; ++collpos) {		x = charmapencode_output('?', mapping, res, respos);		if (x==enc_EXCEPTION) {		    return -1;		}		else if (x==enc_FAILED) {		    raise_encode_exception(exceptionObject, encoding, p, size, collstartpos, collendpos, reason);		    return -1;		}	    }	    /* fall through */	case 3: /* ignore */	    *inpos = collendpos;	    break;	case 4: /* xmlcharrefreplace */	    /* generate replacement (temporarily (mis)uses p) */	    for (collpos = collstartpos; collpos < collendpos; ++collpos) {		char buffer[2+29+1+1];		char *cp;		sprintf(buffer, "&#%d;", (int)p[collpos]);		for (cp = buffer; *cp; ++cp) {		    x = charmapencode_output(*cp, mapping, res, respos);		    if (x==enc_EXCEPTION)			return -1;		    else if (x==enc_FAILED) {			raise_encode_exception(exceptionObject, encoding, p, size, collstartpos, collendpos, reason);			return -1;		    }		}	    }	    *inpos = collendpos;	    break;	default:	    repunicode = unicode_encode_call_errorhandler(errors, errorHandler,		encoding, reason, p, size, exceptionObject,		collstartpos, collendpos, &newpos);	    if (repunicode == NULL)		return -1;	    /* generate replacement  */	    repsize = PyUnicode_GET_SIZE(repunicode);	    for (uni2 = PyUnicode_AS_UNICODE(repunicode); repsize-->0; ++uni2) {		x = charmapencode_output(*uni2, mapping, res, respos);		if (x==enc_EXCEPTION) {		    return -1;		}		else if (x==enc_FAILED) {		    Py_DECREF(repunicode);		    raise_encode_exception(exceptionObject, encoding, p, size, collstartpos, collendpos, reason);		    return -1;		}	    }	    *inpos = newpos;	    Py_DECREF(repunicode);    }    return 0;} PyObject *PyUnicode_EncodeCharmap(const Py_UNICODE *p,				  Py_ssize_t size,				  PyObject *mapping,				  const char *errors){    /* output object */    PyObject *res = NULL;    /* current input position */    Py_ssize_t inpos = 0;    /* current output position */    Py_ssize_t respos = 0;    PyObject *errorHandler = NULL;    PyObject *exc = NULL;    /* the following variable is used for caching string comparisons     * -1=not initialized, 0=unknown, 1=strict, 2=replace,     * 3=ignore, 4=xmlcharrefreplace */    int known_errorHandler = -1;     /* Default to Latin-1 */    if (mapping == NULL)	return PyUnicode_EncodeLatin1(p, size, errors);     /* allocate enough for a simple encoding without       replacements, if we need more, we'll resize */    res = PyString_FromStringAndSize(NULL, size);    if (res == NULL)        goto onError;    if (size == 0)	return res;     while (inpos<size) {	/* try to encode it */	charmapencode_result x = charmapencode_output(p[inpos], mapping, &res, &respos);	if (x==enc_EXCEPTION) /* error */	    goto onError;	if (x==enc_FAILED) { /* unencodable character */	    if (charmap_encoding_error(p, size, &inpos, mapping,		&exc,		&known_errorHandler, &errorHandler, errors,		&res, &respos)) {		goto onError;	    }	}	else	    /* done with this character => adjust input position */	    ++inpos;    }     /* Resize if we allocated to much */    if (respos<PyString_GET_SIZE(res)) {	if (_PyString_Resize(&res, respos))	    goto onError;    }    Py_XDECREF(exc);    Py_XDECREF(errorHandler);    return res;     onError:    Py_XDECREF(res);    Py_XDECREF(exc);    Py_XDECREF(errorHandler);    return NULL;} PyObject *PyUnicode_AsCharmapString(PyObject *unicode,				    PyObject *mapping){    if (!PyUnicode_Check(unicode) || mapping == NULL) {	PyErr_BadArgument();	return NULL;    }    return PyUnicode_EncodeCharmap(PyUnicode_AS_UNICODE(unicode),				   PyUnicode_GET_SIZE(unicode),				   mapping,				   NULL);} /* create or adjust a UnicodeTranslateError */static void make_translate_exception(PyObject **exceptionObject,    const Py_UNICODE *unicode, Py_ssize_t size,    Py_ssize_t startpos, Py_ssize_t endpos,    const char *reason){    if (*exceptionObject == NULL) {    	*exceptionObject = PyUnicodeTranslateError_Create(	    unicode, size, startpos, endpos, reason);    }    else {	if (PyUnicodeTranslateError_SetStart(*exceptionObject, startpos))	    goto onError;	if (PyUnicodeTranslateError_SetEnd(*exceptionObject, endpos))	    goto onError;	if (PyUnicodeTranslateError_SetReason(*exceptionObject, reason))	    goto onError;	return;	onError:	Py_DECREF(*exceptionObject);	*exceptionObject = NULL;    }} /* raises a UnicodeTranslateError */static void raise_translate_exception(PyObject **exceptionObject,    const Py_UNICODE *unicode, Py_ssize_t size,    Py_ssize_t startpos, Py_ssize_t endpos,    const char *reason){    make_translate_exception(exceptionObject,	unicode, size, startpos, endpos, reason);    if (*exceptionObject != NULL)	PyCodec_StrictErrors(*exceptionObject);} /* error handling callback helper:   build arguments, call the callback and check the arguments,   put the result into newpos and return the replacement string, which   has to be freed by the caller */static PyObject *unicode_translate_call_errorhandler(const char *errors,    PyObject **errorHandler,    const char *reason,    const Py_UNICODE *unicode, Py_ssize_t size, PyObject **exceptionObject,    Py_ssize_t startpos, Py_ssize_t endpos,    Py_ssize_t *newpos){    static char *argparse = "O!n;translating error handler must return (unicode, int) tuple";     Py_ssize_t i_newpos;    PyObject *restuple;    PyObject *resunicode;     if (*errorHandler == NULL) {	*errorHandler = PyCodec_LookupError(errors);        if (*errorHandler == NULL)	    return NULL;    }     make_translate_exception(exceptionObject,	unicode, size, startpos, endpos, reason);    if (*exceptionObject == NULL)	return NULL;     restuple = PyObject_CallFunctionObjArgs(	*errorHandler, *exceptionObject, NULL);    if (restuple == NULL)	return NULL;    if (!PyTuple_Check(restuple)) {	PyErr_Format(PyExc_TypeError, &argparse[4]);	Py_DECREF(restuple);	return NULL;    }    if (!PyArg_ParseTuple(restuple, argparse, &PyUnicode_Type,	&resunicode, &i_newpos)) {	Py_DECREF(restuple);	return NULL;    }    if (i_newpos<0)	*newpos = size+i_newpos;    else        *newpos = i_newpos;    if (*newpos<0 || *newpos>size) {	PyErr_Format(PyExc_IndexError, "position %zd from error handler out of bounds", *newpos);	Py_DECREF(restuple);	return NULL;    }    Py_INCREF(resunicode);    Py_DECREF(restuple);    return resunicode;} /* Lookup the character ch in the mapping and put the result in result,   which must be decrefed by the caller.   Return 0 on success, -1 on error */staticint charmaptranslate_lookup(Py_UNICODE c, PyObject *mapping, PyObject **result){    PyObject *w = PyInt_FromLong((long)c);    PyObject *x;     if (w == NULL)	 return -1;    x = PyObject_GetItem(mapping, w);    Py_DECREF(w);    if (x == NULL) {	if (PyErr_ExceptionMatches(PyExc_LookupError)) {	    /* No mapping found means: use 1:1 mapping. */	    PyErr_Clear();	    *result = NULL;	    return 0;	} else	    return -1;    }    else if (x == Py_None) {	*result = x;	return 0;    }    else if (PyInt_Check(x)) {	long value = PyInt_AS_LONG(x);	long max = PyUnicode_GetMax();	if (value < 0 || value > max) {	    PyErr_Format(PyExc_TypeError,			     "character mapping must be in range(0x%lx)", max+1);	    Py_DECREF(x);	    return -1;	}	*result = x;	return 0;    }    else if (PyUnicode_Check(x)) {	*result = x;	return 0;    }    else {	/* wrong return value */	PyErr_SetString(PyExc_TypeError,	      "character mapping must return integer, None or unicode");	Py_DECREF(x);	return -1;    }}/* ensure that *outobj is at least requiredsize characters long,if not reallocate and adjust various state variables.Return 0 on success, -1 on error */staticint charmaptranslate_makespace(PyObject **outobj, Py_UNICODE **outp,    Py_ssize_t requiredsize){    Py_ssize_t oldsize = PyUnicode_GET_SIZE(*outobj);    if (requiredsize > oldsize) {	/* remember old output position */	Py_ssize_t outpos = *outp-PyUnicode_AS_UNICODE(*outobj);	/* exponentially overallocate to minimize reallocations */	if (requiredsize < 2 * oldsize)	    requiredsize = 2 * oldsize;	if (_PyUnicode_Resize(outobj, requiredsize) < 0)	    return -1;	*outp = PyUnicode_AS_UNICODE(*outobj) + outpos;    }    return 0;}/* lookup the character, put the result in the output string and adjust   various state variables. Return a new reference to the object that   was put in the output buffer in *result, or Py_None, if the mapping was   undefined (in which case no character was written).   The called must decref result.   Return 0 on success, -1 on error. */staticint charmaptranslate_output(const Py_UNICODE *startinp, const Py_UNICODE *curinp,    Py_ssize_t insize, PyObject *mapping, PyObject **outobj, Py_UNICODE **outp,    PyObject **res){    if (charmaptranslate_lookup(*curinp, mapping, res))	return -1;    if (*res==NULL) {	/* not found => default to 1:1 mapping */	*(*outp)++ = *curinp;    }    else if (*res==Py_None)	;    else if (PyInt_Check(*res)) {	/* no overflow check, because we know that the space is enough */	*(*outp)++ = (Py_UNICODE)PyInt_AS_LONG(*res);    }    else if (PyUnicode_Check(*res)) {	Py_ssize_t repsize = PyUnicode_GET_SIZE(*res);	if (repsize==1) {	    /* no overflow check, because we know that the space is enough */	    *(*outp)++ = *PyUnicode_AS_UNICODE(*res);	}	else if (repsize!=0) {	    /* more than one character */	    Py_ssize_t requiredsize = (*outp-PyUnicode_AS_UNICODE(*outobj)) +		(insize - (curinp-startinp)) +		repsize - 1;	    if (charmaptranslate_makespace(outobj, outp, requiredsize))		return -1;	    memcpy(*outp, PyUnicode_AS_UNICODE(*res), sizeof(Py_UNICODE)*repsize);	    *outp += repsize;	}    }    else	return -1;    return 0;} PyObject *PyUnicode_TranslateCharmap(const Py_UNICODE *p,				     Py_ssize_t size,				     PyObject *mapping,				     const char *errors){    /* output object */    PyObject *res = NULL;    /* pointers to the beginning and end+1 of input */    const Py_UNICODE *startp = p;    const Py_UNICODE *endp = p + size;    /* pointer into the output */    Py_UNICODE *str;    /* current output position */    Py_ssize_t respos = 0;    char *reason = "character maps to <undefined>";    PyObject *errorHandler = NULL;    PyObject *exc = NULL;    /* the following variable is used for caching string comparisons     * -1=not initialized, 0=unknown, 1=strict, 2=replace,     * 3=ignore, 4=xmlcharrefreplace */    int known_errorHandler = -1;     if (mapping == NULL) {	PyErr_BadArgument();	return NULL;    }     /* allocate enough for a simple 1:1 translation without       replacements, if we need more, we'll resize */    res = PyUnicode_FromUnicode(NULL, size);    if (res == NULL)	goto onError;    if (size == 0)	return res;    str = PyUnicode_AS_UNICODE(res);     while (p<endp) {	/* try to encode it */	PyObject *x = NULL;	if (charmaptranslate_output(startp, p, size, mapping, &res, &str, &x)) {	    Py_XDECREF(x);	    goto onError;	}	Py_XDECREF(x);	if (x!=Py_None) /* it worked => adjust input pointer */	    ++p;	else { /* untranslatable character */	    PyObject *repunicode = NULL; /* initialize to prevent gcc warning */	    Py_ssize_t repsize;	    Py_ssize_t newpos;

Lines 3501–4000 of 8067. Previous lines