MCPcopy Create free account
hub / github.com/simplejson/simplejson / scanstring_unicode

Function scanstring_unicode

simplejson/_speedups.c:1483–1669  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

1481
1482#if PY_VERSION_HEX >= 0x030E0000
1483static PyObject *
1484scanstring_unicode(_speedups_state *state, PyObject *pystr, Py_ssize_t end,
1485 int strict, Py_ssize_t *next_end_ptr)
1486{
1487 /* Python 3.14+: use PyUnicodeWriter instead of a chunks list.
1488 * The writer is lazily created on the first escape sequence so that
1489 * the common no-escape path returns a cheap PyUnicode_Substring. */
1490 PyObject *rval;
1491 Py_ssize_t begin = end - 1;
1492 Py_ssize_t next = begin;
1493 int kind = PyUnicode_KIND(pystr);
1494 Py_ssize_t len = PyUnicode_GET_LENGTH(pystr);
1495 void *buf = PyUnicode_DATA(pystr);
1496 PyUnicodeWriter *writer = NULL;
1497 Py_ssize_t literal_start;
1498
1499 if (len == end) {
1500 raise_errmsg(state, ERR_STRING_UNTERMINATED, pystr, begin);
1501 goto bail;
1502 }
1503 else if (end < 0 || len < end) {
1504 /* Out-of-range end: match py_scanstring, which raises
1505 * JSONDecodeError("Unterminated string starting at") so that
1506 * user code using `except JSONDecodeError` catches the C path
1507 * the same way it catches the pure-Python path. */
1508 raise_errmsg(state, ERR_STRING_UNTERMINATED, pystr, begin);
1509 goto bail;
1510 }
1511
1512 literal_start = end;
1513 while (1) {
1514 /* Find the end of the string or the next escape */
1515 JSON_UNICHR c = 0;
1516 for (next = end; next < len; next++) {
1517 c = PyUnicode_READ(kind, buf, next);
1518 if (c == '"' || c == '\\') {
1519 break;
1520 }
1521 else if (strict && c <= 0x1f) {
1522 raise_errmsg(state, ERR_STRING_CONTROL, pystr, next);
1523 goto bail;
1524 }
1525 }
1526 if (!(c == '"' || c == '\\')) {
1527 raise_errmsg(state, ERR_STRING_UNTERMINATED, pystr, begin);
1528 goto bail;
1529 }
1530 next++;
1531 if (c == '"') {
1532 end = next;
1533 break;
1534 }
1535 /* Backslash escape — ensure writer exists and flush the
1536 * literal span [literal_start, next-1). */
1537 if (writer == NULL) {
1538 writer = PyUnicodeWriter_Create(len - begin);
1539 if (writer == NULL)
1540 goto bail;

Callers 1

py_scanstringFunction · 0.85

Calls 2

raise_errmsgFunction · 0.85
join_list_unicodeFunction · 0.85

Tested by

no test coverage detected

Used in the wild real call sites across dependent graphs

searching dependent graphs…