static int
encoder_clear(PyEncoderObject *self);
static int
-encoder_listencode_list(PyEncoderObject *s, _PyUnicodeWriter *writer, PyObject *seq, Py_ssize_t indent_level);
+encoder_listencode_list(PyEncoderObject *s, _PyUnicodeWriter *writer, PyObject *seq, PyObject *newline_indent);
static int
-encoder_listencode_obj(PyEncoderObject *s, _PyUnicodeWriter *writer, PyObject *obj, Py_ssize_t indent_level);
+encoder_listencode_obj(PyEncoderObject *s, _PyUnicodeWriter *writer, PyObject *obj, PyObject *newline_indent);
static int
-encoder_listencode_dict(PyEncoderObject *s, _PyUnicodeWriter *writer, PyObject *dct, Py_ssize_t indent_level);
+encoder_listencode_dict(PyEncoderObject *s, _PyUnicodeWriter *writer, PyObject *dct, PyObject *newline_indent);
static PyObject *
_encoded_const(PyObject *obj);
static void
return (PyObject *)s;
}
+static PyObject *
+_create_newline_indent(PyObject *indent, Py_ssize_t indent_level)
+{
+ PyObject *newline_indent = PyUnicode_FromOrdinal('\n');
+ if (newline_indent != NULL && indent_level) {
+ PyUnicode_AppendAndDel(&newline_indent,
+ PySequence_Repeat(indent, indent_level));
+ }
+ return newline_indent;
+}
+
static PyObject *
encoder_call(PyEncoderObject *self, PyObject *args, PyObject *kwds)
{
_PyUnicodeWriter_Init(&writer);
writer.overallocate = 1;
- if (encoder_listencode_obj(self, &writer, obj, indent_level)) {
+ PyObject *newline_indent = NULL;
+ if (self->indent != Py_None) {
+ newline_indent = _create_newline_indent(self->indent, indent_level);
+ if (newline_indent == NULL) {
+ _PyUnicodeWriter_Dealloc(&writer);
+ return NULL;
+ }
+ }
+ if (encoder_listencode_obj(self, &writer, obj, newline_indent)) {
_PyUnicodeWriter_Dealloc(&writer);
+ Py_XDECREF(newline_indent);
return NULL;
}
+ Py_XDECREF(newline_indent);
result = PyTuple_New(1);
if (result == NULL ||
static int
encoder_listencode_obj(PyEncoderObject *s, _PyUnicodeWriter *writer,
- PyObject *obj, Py_ssize_t indent_level)
+ PyObject *obj, PyObject *newline_indent)
{
/* Encode Python object obj to a JSON term */
PyObject *newobj;
else if (PyList_Check(obj) || PyTuple_Check(obj)) {
if (_Py_EnterRecursiveCall(" while encoding a JSON object"))
return -1;
- rv = encoder_listencode_list(s, writer, obj, indent_level);
+ rv = encoder_listencode_list(s, writer, obj, newline_indent);
_Py_LeaveRecursiveCall();
return rv;
}
else if (PyDict_Check(obj)) {
if (_Py_EnterRecursiveCall(" while encoding a JSON object"))
return -1;
- rv = encoder_listencode_dict(s, writer, obj, indent_level);
+ rv = encoder_listencode_dict(s, writer, obj, newline_indent);
_Py_LeaveRecursiveCall();
return rv;
}
Py_XDECREF(ident);
return -1;
}
- rv = encoder_listencode_obj(s, writer, newobj, indent_level);
+ rv = encoder_listencode_obj(s, writer, newobj, newline_indent);
_Py_LeaveRecursiveCall();
Py_DECREF(newobj);
static int
encoder_encode_key_value(PyEncoderObject *s, _PyUnicodeWriter *writer, bool *first,
- PyObject *key, PyObject *value, Py_ssize_t indent_level)
+ PyObject *key, PyObject *value,
+ PyObject *newline_indent,
+ PyObject *item_separator)
{
PyObject *keystr = NULL;
PyObject *encoded;
*first = false;
}
else {
- if (_PyUnicodeWriter_WriteStr(writer, s->item_separator) < 0) {
+ if (_PyUnicodeWriter_WriteStr(writer, item_separator) < 0) {
Py_DECREF(keystr);
return -1;
}
if (_PyUnicodeWriter_WriteStr(writer, s->key_separator) < 0) {
return -1;
}
- if (encoder_listencode_obj(s, writer, value, indent_level) < 0) {
+ if (encoder_listencode_obj(s, writer, value, newline_indent) < 0) {
return -1;
}
return 0;
static int
encoder_listencode_dict(PyEncoderObject *s, _PyUnicodeWriter *writer,
- PyObject *dct, Py_ssize_t indent_level)
+ PyObject *dct, PyObject *newline_indent)
{
/* Encode Python dict dct a JSON term */
PyObject *ident = NULL;
PyObject *items = NULL;
PyObject *key, *value;
bool first = true;
+ PyObject *new_newline_indent = NULL;
+ PyObject *separator_indent = NULL;
if (PyDict_GET_SIZE(dct) == 0) /* Fast path */
return _PyUnicodeWriter_WriteASCIIString(writer, "{}", 2);
if (_PyUnicodeWriter_WriteChar(writer, '{'))
goto bail;
+ PyObject *current_item_separator = s->item_separator; // borrowed reference
if (s->indent != Py_None) {
- /* TODO: DOES NOT RUN */
- indent_level += 1;
- /*
- newline_indent = '\n' + (' ' * (_indent * _current_indent_level))
- separator = _item_separator + newline_indent
- buf += newline_indent
- */
+ new_newline_indent = PyUnicode_Concat(newline_indent, s->indent);
+ if (new_newline_indent == NULL) {
+ goto bail;
+ }
+ separator_indent = PyUnicode_Concat(current_item_separator, new_newline_indent);
+ if (separator_indent == NULL) {
+ goto bail;
+ }
+ // update item separator with a borrowed reference
+ current_item_separator = separator_indent;
+ if (_PyUnicodeWriter_WriteStr(writer, new_newline_indent) < 0) {
+ goto bail;
+ }
}
if (s->sort_keys || !PyDict_CheckExact(dct)) {
key = PyTuple_GET_ITEM(item, 0);
value = PyTuple_GET_ITEM(item, 1);
- if (encoder_encode_key_value(s, writer, &first, key, value, indent_level) < 0)
+ if (encoder_encode_key_value(s, writer, &first, key, value,
+ new_newline_indent,
+ current_item_separator) < 0)
goto bail;
}
Py_CLEAR(items);
} else {
Py_ssize_t pos = 0;
while (PyDict_Next(dct, &pos, &key, &value)) {
- if (encoder_encode_key_value(s, writer, &first, key, value, indent_level) < 0)
+ if (encoder_encode_key_value(s, writer, &first, key, value,
+ new_newline_indent,
+ current_item_separator) < 0)
goto bail;
}
}
goto bail;
Py_CLEAR(ident);
}
- /* TODO DOES NOT RUN; dead code
if (s->indent != Py_None) {
- indent_level -= 1;
+ Py_CLEAR(new_newline_indent);
+ Py_CLEAR(separator_indent);
+
+ if (_PyUnicodeWriter_WriteStr(writer, newline_indent) < 0) {
+ goto bail;
+ }
+ }
- yield '\n' + (' ' * (_indent * _current_indent_level))
- }*/
if (_PyUnicodeWriter_WriteChar(writer, '}'))
goto bail;
return 0;
bail:
Py_XDECREF(items);
Py_XDECREF(ident);
+ Py_XDECREF(separator_indent);
+ Py_XDECREF(new_newline_indent);
return -1;
}
static int
encoder_listencode_list(PyEncoderObject *s, _PyUnicodeWriter *writer,
- PyObject *seq, Py_ssize_t indent_level)
+ PyObject *seq, PyObject *newline_indent)
{
PyObject *ident = NULL;
PyObject *s_fast = NULL;
Py_ssize_t i;
+ PyObject *new_newline_indent = NULL;
+ PyObject *separator_indent = NULL;
ident = NULL;
s_fast = PySequence_Fast(seq, "_iterencode_list needs a sequence");
if (_PyUnicodeWriter_WriteChar(writer, '['))
goto bail;
+
+ PyObject *separator = s->item_separator; // borrowed reference
if (s->indent != Py_None) {
- /* TODO: DOES NOT RUN */
- indent_level += 1;
- /*
- newline_indent = '\n' + (' ' * (_indent * _current_indent_level))
- separator = _item_separator + newline_indent
- buf += newline_indent
- */
+ new_newline_indent = PyUnicode_Concat(newline_indent, s->indent);
+ if (new_newline_indent == NULL) {
+ goto bail;
+ }
+
+ if (_PyUnicodeWriter_WriteStr(writer, new_newline_indent) < 0) {
+ goto bail;
+ }
+
+ separator_indent = PyUnicode_Concat(separator, new_newline_indent);
+ if (separator_indent == NULL) {
+ goto bail;
+ }
+ separator = separator_indent; // assign separator with borrowed reference
}
for (i = 0; i < PySequence_Fast_GET_SIZE(s_fast); i++) {
PyObject *obj = PySequence_Fast_GET_ITEM(s_fast, i);
if (i) {
- if (_PyUnicodeWriter_WriteStr(writer, s->item_separator))
+ if (_PyUnicodeWriter_WriteStr(writer, separator) < 0)
goto bail;
}
- if (encoder_listencode_obj(s, writer, obj, indent_level))
+ if (encoder_listencode_obj(s, writer, obj, new_newline_indent))
goto bail;
}
if (ident != NULL) {
Py_CLEAR(ident);
}
- /* TODO: DOES NOT RUN
if (s->indent != Py_None) {
- indent_level -= 1;
+ Py_CLEAR(new_newline_indent);
+ Py_CLEAR(separator_indent);
+ if (_PyUnicodeWriter_WriteStr(writer, newline_indent) < 0) {
+ goto bail;
+ }
+ }
- yield '\n' + (' ' * (_indent * _current_indent_level))
- }*/
if (_PyUnicodeWriter_WriteChar(writer, ']'))
goto bail;
Py_DECREF(s_fast);
bail:
Py_XDECREF(ident);
Py_DECREF(s_fast);
+ Py_XDECREF(separator_indent);
+ Py_XDECREF(new_newline_indent);
return -1;
}
return 0;
}
-PyDoc_STRVAR(encoder_doc, "_iterencode(obj, _current_indent_level) -> iterable");
+PyDoc_STRVAR(encoder_doc, "Encoder(markers, default, encoder, indent, key_separator, item_separator, sort_keys, skipkeys, allow_nan)");
static PyType_Slot PyEncoderType_slots[] = {
{Py_tp_doc, (void *)encoder_doc},