Dont use a macro for as_text_generic

This commit is contained in:
Kovid Goyal 2020-02-25 15:33:12 +05:30
parent b7d12de0a7
commit af8fdf1dbe
No known key found for this signature in database
GPG key ID: 06BC317B515ACE7C
5 changed files with 74 additions and 56 deletions

View file

@ -379,12 +379,23 @@ end:
Py_RETURN_NONE;
}
typedef struct {
Line line;
HistoryBuf *self;
} GetLineWrapper;
static Line*
get_line_wrapper(void *x, int y) {
GetLineWrapper *glw = x;
get_line(glw->self, y, &glw->line);
return &glw->line;
}
static PyObject*
as_text(HistoryBuf *self, PyObject *args) {
Line l = {.xnum=self->xnum};
#define gl(self, y) get_line(self, y, &l);
as_text_generic(args, self, gl, self->count, self->xnum);
#undef gl
GetLineWrapper glw = {.self=self};
glw.line.xnum = self->xnum;
return as_text_generic(args, &glw, get_line_wrapper, self->count, self->xnum);
}

View file

@ -421,14 +421,15 @@ as_ansi(LineBuf *self, PyObject *callback) {
}
static inline Line*
get_line(LineBuf *self, index_type y) {
linebuf_init_line(self, y);
get_line(void *x, int y) {
LineBuf *self = (LineBuf*)x;
linebuf_init_line(self, MAX(0, y));
return self->line;
}
static PyObject*
as_text(LineBuf *self, PyObject *args) {
as_text_generic(args, self, get_line, self->ynum, self->xnum);
return as_text_generic(args, self, get_line, self->ynum, self->xnum);
}

View file

@ -737,6 +737,51 @@ mark_text_in_line(PyObject *marker, Line *line) {
Py_DECREF(text);
}
PyObject*
as_text_generic(PyObject *args, void *container, get_line_func get_line, index_type lines, index_type columns) {
PyObject *callback;
int as_ansi = 0, insert_wrap_markers = 0;
if (!PyArg_ParseTuple(args, "O|pp", &callback, &as_ansi, &insert_wrap_markers)) return NULL;
PyObject *ret = NULL, *t = NULL;
Py_UCS4 *buf = NULL;
PyObject *nl = PyUnicode_FromString("\n");
PyObject *cr = PyUnicode_FromString("\r");
const GPUCell *prev_cell = NULL;
if (nl == NULL || cr == NULL) goto end;
if (as_ansi) {
buf = malloc(sizeof(Py_UCS4) * columns * 100);
if (buf == NULL) { PyErr_NoMemory(); goto end; }
}
for (index_type y = 0; y < lines; y++) {
Line *line = get_line(container, y);
if (!line->continued && y > 0) {
ret = PyObject_CallFunctionObjArgs(callback, nl, NULL);
if (ret == NULL) goto end;
Py_CLEAR(ret);
}
if (as_ansi) {
bool truncated;
index_type num = line_as_ansi(line, buf, columns * 100 - 2, &truncated, &prev_cell);
t = PyUnicode_FromKindAndData(PyUnicode_4BYTE_KIND, buf, num);
} else {
t = line_as_unicode(line);
}
if (t == NULL) goto end;
ret = PyObject_CallFunctionObjArgs(callback, t, NULL);
Py_DECREF(t); if (ret == NULL) goto end; Py_DECREF(ret);
if (insert_wrap_markers) {
ret = PyObject_CallFunctionObjArgs(callback, cr, NULL);
if (ret == NULL) goto end;
Py_CLEAR(ret);
}
}
end:
Py_CLEAR(nl); Py_CLEAR(cr); free(buf);
if (PyErr_Occurred()) return NULL;
Py_RETURN_NONE;
}
// Boilerplate {{{
static PyObject*
copy_char(Line* self, PyObject *args);

View file

@ -54,6 +54,7 @@ line_reset_cells(Line *line, index_type start, index_type num, GPUCell *gpu_cell
memcpy(line->cpu_cells + start, cpu_cells + start, sizeof(CPUCell) * num);
}
typedef Line*(get_line_func)(void *, int);
void line_clear_text(Line *self, unsigned int at, unsigned int num, char_type ch);
void line_apply_cursor(Line *self, Cursor *cursor, unsigned int at, unsigned int num, bool clear_char);
void line_set_char(Line *, unsigned int , uint32_t , unsigned int , Cursor *, bool);
@ -92,47 +93,4 @@ void historybuf_refresh_sprite_positions(HistoryBuf *self);
void historybuf_clear(HistoryBuf *self);
void mark_text_in_line(PyObject *marker, Line *line);
bool line_has_mark(Line *, attrs_type mark);
#define as_text_generic(args, container, get_line, lines, columns) { \
PyObject *callback; \
int as_ansi = 0, insert_wrap_markers = 0; \
if (!PyArg_ParseTuple(args, "O|pp", &callback, &as_ansi, &insert_wrap_markers)) return NULL; \
PyObject *ret = NULL, *t = NULL; \
Py_UCS4 *buf = NULL; \
PyObject *nl = PyUnicode_FromString("\n"); \
PyObject *cr = PyUnicode_FromString("\r"); \
const GPUCell *prev_cell = NULL; \
if (nl == NULL || cr == NULL) goto end; \
if (as_ansi) { \
buf = malloc(sizeof(Py_UCS4) * columns * 100); \
if (buf == NULL) { PyErr_NoMemory(); goto end; } \
} \
for (index_type y = 0; y < lines; y++) { \
Line *line = get_line(container, y); \
if (!line->continued && y > 0) { \
ret = PyObject_CallFunctionObjArgs(callback, nl, NULL); \
if (ret == NULL) goto end; \
Py_CLEAR(ret); \
} \
if (as_ansi) { \
bool truncated; \
index_type num = line_as_ansi(line, buf, columns * 100 - 2, &truncated, &prev_cell); \
t = PyUnicode_FromKindAndData(PyUnicode_4BYTE_KIND, buf, num); \
} else { \
t = line_as_unicode(line); \
} \
if (t == NULL) goto end; \
ret = PyObject_CallFunctionObjArgs(callback, t, NULL); \
Py_DECREF(t); if (ret == NULL) goto end; Py_DECREF(ret); \
if (insert_wrap_markers) { \
ret = PyObject_CallFunctionObjArgs(callback, cr, NULL); \
if (ret == NULL) goto end; \
Py_CLEAR(ret); \
}\
} \
end: \
Py_CLEAR(nl); Py_CLEAR(cr); free(buf); \
if (PyErr_Occurred()) return NULL; \
Py_RETURN_NONE; \
}
PyObject* as_text_generic(PyObject *args, void *container, get_line_func get_line, index_type lines, index_type columns);

View file

@ -1749,26 +1749,29 @@ set_pending_timeout(Screen *self, PyObject *val) {
return ans;
}
static Line* get_visual_line(void *x, int y) { return visual_line_(x, y); }
static Line* get_range_line(void *x, int y) { return range_line_(x, y); }
static PyObject*
as_text(Screen *self, PyObject *args) {
as_text_generic(args, self, visual_line_, self->lines, self->columns);
return as_text_generic(args, self, get_visual_line, self->lines, self->columns);
}
static PyObject*
as_text_non_visual(Screen *self, PyObject *args) {
as_text_generic(args, self, range_line_, self->lines, self->columns);
return as_text_generic(args, self, get_range_line, self->lines, self->columns);
}
static inline PyObject*
as_text_generic_wrapper(Screen *self, PyObject *args, Line*(get_line)(Screen *, int)) {
as_text_generic(args, self, get_line, self->lines, self->columns);
as_text_generic_wrapper(Screen *self, PyObject *args, get_line_func get_line) {
return as_text_generic(args, self, get_line, self->lines, self->columns);
}
static PyObject*
as_text_alternate(Screen *self, PyObject *args) {
LineBuf *original = self->linebuf;
self->linebuf = original == self->main_linebuf ? self->alt_linebuf : self->main_linebuf;
PyObject *ans = as_text_generic_wrapper(self, args, range_line_);
PyObject *ans = as_text_generic_wrapper(self, args, get_range_line);
self->linebuf = original;
return ans;
}