mirror of
				https://github.com/python/cpython.git
				synced 2025-11-04 15:41:43 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			115 lines
		
	
	
	
		
			2.4 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			115 lines
		
	
	
	
		
			2.4 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/* Accumulator struct implementation */
 | 
						|
 | 
						|
#include "Python.h"
 | 
						|
#include "accu.h"
 | 
						|
 | 
						|
static PyObject *
 | 
						|
join_list_unicode(PyObject *lst)
 | 
						|
{
 | 
						|
    /* return ''.join(lst) */
 | 
						|
    PyObject *sep, *ret;
 | 
						|
    sep = PyUnicode_FromStringAndSize("", 0);
 | 
						|
    ret = PyUnicode_Join(sep, lst);
 | 
						|
    Py_DECREF(sep);
 | 
						|
    return ret;
 | 
						|
}
 | 
						|
 | 
						|
int
 | 
						|
_PyAccu_Init(_PyAccu *acc)
 | 
						|
{
 | 
						|
    /* Lazily allocated */
 | 
						|
    acc->large = NULL;
 | 
						|
    acc->small = PyList_New(0);
 | 
						|
    if (acc->small == NULL)
 | 
						|
        return -1;
 | 
						|
    return 0;
 | 
						|
}
 | 
						|
 | 
						|
static int
 | 
						|
flush_accumulator(_PyAccu *acc)
 | 
						|
{
 | 
						|
    Py_ssize_t nsmall = PyList_GET_SIZE(acc->small);
 | 
						|
    if (nsmall) {
 | 
						|
        int ret;
 | 
						|
        PyObject *joined;
 | 
						|
        if (acc->large == NULL) {
 | 
						|
            acc->large = PyList_New(0);
 | 
						|
            if (acc->large == NULL)
 | 
						|
                return -1;
 | 
						|
        }
 | 
						|
        joined = join_list_unicode(acc->small);
 | 
						|
        if (joined == NULL)
 | 
						|
            return -1;
 | 
						|
        if (PyList_SetSlice(acc->small, 0, nsmall, NULL)) {
 | 
						|
            Py_DECREF(joined);
 | 
						|
            return -1;
 | 
						|
        }
 | 
						|
        ret = PyList_Append(acc->large, joined);
 | 
						|
        Py_DECREF(joined);
 | 
						|
        return ret;
 | 
						|
    }
 | 
						|
    return 0;
 | 
						|
}
 | 
						|
 | 
						|
int
 | 
						|
_PyAccu_Accumulate(_PyAccu *acc, PyObject *unicode)
 | 
						|
{
 | 
						|
    Py_ssize_t nsmall;
 | 
						|
    assert(PyUnicode_Check(unicode));
 | 
						|
 | 
						|
    if (PyList_Append(acc->small, unicode))
 | 
						|
        return -1;
 | 
						|
    nsmall = PyList_GET_SIZE(acc->small);
 | 
						|
    /* Each item in a list of unicode objects has an overhead (in 64-bit
 | 
						|
     * builds) of:
 | 
						|
     *   - 8 bytes for the list slot
 | 
						|
     *   - 56 bytes for the header of the unicode object
 | 
						|
     * that is, 64 bytes.  100000 such objects waste more than 6MB
 | 
						|
     * compared to a single concatenated string.
 | 
						|
     */
 | 
						|
    if (nsmall < 100000)
 | 
						|
        return 0;
 | 
						|
    return flush_accumulator(acc);
 | 
						|
}
 | 
						|
 | 
						|
PyObject *
 | 
						|
_PyAccu_FinishAsList(_PyAccu *acc)
 | 
						|
{
 | 
						|
    int ret;
 | 
						|
    PyObject *res;
 | 
						|
 | 
						|
    ret = flush_accumulator(acc);
 | 
						|
    Py_CLEAR(acc->small);
 | 
						|
    if (ret) {
 | 
						|
        Py_CLEAR(acc->large);
 | 
						|
        return NULL;
 | 
						|
    }
 | 
						|
    res = acc->large;
 | 
						|
    acc->large = NULL;
 | 
						|
    return res;
 | 
						|
}
 | 
						|
 | 
						|
PyObject *
 | 
						|
_PyAccu_Finish(_PyAccu *acc)
 | 
						|
{
 | 
						|
    PyObject *list, *res;
 | 
						|
    if (acc->large == NULL) {
 | 
						|
        list = acc->small;
 | 
						|
        acc->small = NULL;
 | 
						|
    }
 | 
						|
    else {
 | 
						|
        list = _PyAccu_FinishAsList(acc);
 | 
						|
        if (!list)
 | 
						|
            return NULL;
 | 
						|
    }
 | 
						|
    res = join_list_unicode(list);
 | 
						|
    Py_DECREF(list);
 | 
						|
    return res;
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
_PyAccu_Destroy(_PyAccu *acc)
 | 
						|
{
 | 
						|
    Py_CLEAR(acc->small);
 | 
						|
    Py_CLEAR(acc->large);
 | 
						|
}
 |