Wrap the transform_properties function for python

This commit is contained in:
Kovid Goyal 2021-03-19 08:49:53 +05:30
parent b08794a6c2
commit c701781014
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C

View File

@ -607,25 +607,28 @@ typedef std::bitset<NUM_OF_BLOCK_TYPE_FLAGS> BlockTypeFlags;
class InputStream { class InputStream {
private: private:
const char32_t *src; int kind;
size_t pos; void *data;
const size_t src_sz; const size_t src_sz;
size_t pos;
char32_t read(size_t i) const { return PyUnicode_READ(kind, data, i); }
char32_t peek_one(size_t at, unsigned *consumed) const { char32_t peek_one(size_t at, unsigned *consumed) const {
if (at >= src_sz) { *consumed = 0; return 0; } if (at >= src_sz) { *consumed = 0; return 0; }
*consumed = 1; *consumed = 1;
char32_t ch = src[at]; char32_t ch = read(at);
if (ch == 0xc) ch = '\n'; if (ch == 0xc) ch = '\n';
else if (ch == '\r') { else if (ch == '\r') {
ch = '\n'; ch = '\n';
if (at + 1 < src_sz && src[at + 1] == '\n') *consumed = 2; if (at + 1 < src_sz && read(at + 1) == '\n') *consumed = 2;
} }
else if (ch == 0 || is_surrogate(ch)) ch = 0xfffd; else if (ch == 0 || is_surrogate(ch)) ch = 0xfffd;
return ch; return ch;
} }
public: public:
InputStream(const char32_t *src, size_t sz) : src(src), pos(0), src_sz(sz) { } InputStream(PyObject *src) : kind(PyUnicode_KIND(src)), data(PyUnicode_DATA(src)), src_sz(PyUnicode_GET_LENGTH(src)), pos(0) { }
char32_t next() { char32_t next() {
unsigned last_step_size; unsigned last_step_size;
@ -636,7 +639,7 @@ class InputStream {
void rewind() { void rewind() {
if (!pos) throw std::logic_error("Cannot rewind already at start of stream"); if (!pos) throw std::logic_error("Cannot rewind already at start of stream");
pos -= (src[pos-1] == '\n' && pos >= 2 && src[pos-2] == '\r') ? 2 : 1; pos -= (read(pos-1) == '\n' && pos >= 2 && read(pos-2) == '\r') ? 2 : 1;
} }
char32_t peek(unsigned amt = 0) const { char32_t peek(unsigned amt = 0) const {
@ -996,9 +999,9 @@ class Parser {
public: public:
Parser(const char32_t *src, const size_t src_sz, const bool is_declaration) : Parser(PyObject *src, PyObject *url_callback = NULL, const bool is_declaration = false) :
ch(0), end_string_with('"'), prev_ch(0), block_types(), states(), escape_buf(), ch(0), end_string_with('"'), prev_ch(0), block_types(), states(), escape_buf(),
escape_buf_pos(0), token_queue(src_sz), input(src, src_sz) escape_buf_pos(0), token_queue(PyUnicode_GET_LENGTH(src), url_callback), input(src)
{ {
BlockTypeFlags initial_block_type; BlockTypeFlags initial_block_type;
initial_block_type.set(DECLARATIONS_ALLOWED); initial_block_type.set(DECLARATIONS_ALLOWED);
@ -1037,15 +1040,26 @@ class Parser {
static PyObject* static PyObject*
transform_properties(const char32_t *src, size_t src_sz, bool is_declaration) { transform_properties(PyObject *src, PyObject *url_callback = NULL, bool is_declaration = false) {
try { try {
std::u32string result; std::u32string result;
Parser parser(src, src_sz, is_declaration); Parser parser(src, url_callback, is_declaration);
parser.parse(result); parser.parse(result);
return PyUnicode_FromKindAndData(PyUnicode_4BYTE_KIND, result.data(), result.size()); return PyUnicode_FromKindAndData(PyUnicode_4BYTE_KIND, result.data(), result.size());
} handle_exceptions("Unknown error while parsing CSS"); } handle_exceptions("Unknown error while parsing CSS");
} }
static PyObject*
transform_properties_python(PyObject *self, PyObject *args, PyObject *kw) {
static const char* kwlist[] = {"url_callback", "is_declaration", NULL};
PyObject *raw, *url_callback = NULL; int is_declaration = 0;
if (!PyArg_ParseTupleAndKeywords(args, kw, "U|Op", (char**)kwlist, &raw, &url_callback, &is_declaration)) return NULL;
if (url_callback && !PyCallable_Check(url_callback)) { PyErr_SetString(PyExc_TypeError, "url_callback must be a callable"); return NULL; }
if (PyUnicode_READY(raw) != 0) return NULL;
PyObject *result = transform_properties(raw, url_callback, is_declaration);
return result;
}
static PyObject* static PyObject*
parse_css_number_python(PyObject *self, PyObject *src) { parse_css_number_python(PyObject *self, PyObject *src) {
if (!PyUnicode_Check(src)) { PyErr_SetString(PyExc_TypeError, "Unicode string required"); return NULL; } if (!PyUnicode_Check(src)) { PyErr_SetString(PyExc_TypeError, "Unicode string required"); return NULL; }
@ -1067,6 +1081,9 @@ static PyMethodDef methods[] = {
{"parse_css_number", parse_css_number_python, METH_O, {"parse_css_number", parse_css_number_python, METH_O,
"Parse a CSS number form a string" "Parse a CSS number form a string"
}, },
{"transform_properties", (PyCFunction)transform_properties_python, METH_VARARGS | METH_KEYWORDS,
"Transform a CSS stylesheet or declaration"
},
{NULL, NULL, 0, NULL} {NULL, NULL, 0, NULL}
}; };