mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-09-03 22:38:41 +09:00
Issue #1738 - Part 2: Implement well-formed JSON stringify
This implements the ES2019 spec for JSON stringification, including lower-casing, properly escaping lone surrogates, etc.
This commit is contained in:
parent
feab62b009
commit
23c9fab20d
2 changed files with 68 additions and 14 deletions
|
|
@ -66,26 +66,67 @@ InfallibleQuote(RangedPtr<const SrcCharT> srcBegin, RangedPtr<const SrcCharT> sr
|
|||
/* Step 1. */
|
||||
*dstPtr++ = '"';
|
||||
|
||||
// XXX: This is a rather ugly in-line definition. Move it somewhere better?
|
||||
auto ToLowerHex = [](uint8_t u) {
|
||||
MOZ_ASSERT(u <= 0xF);
|
||||
return "0123456789abcdef"[u];
|
||||
};
|
||||
|
||||
/* Step 2. */
|
||||
while (srcBegin != srcEnd) {
|
||||
SrcCharT c = *srcBegin++;
|
||||
size_t escapeIndex = c % sizeof(escapeLookup);
|
||||
Latin1Char escaped = escapeLookup[escapeIndex];
|
||||
if (MOZ_LIKELY((escapeIndex != size_t(c)) || !escaped)) {
|
||||
const SrcCharT c = *srcBegin++;
|
||||
|
||||
// Handle the Latin-1 cases.
|
||||
if (MOZ_LIKELY(c < sizeof(escapeLookup))) {
|
||||
Latin1Char escaped = escapeLookup[c];
|
||||
|
||||
// Directly copy non-escaped code points.
|
||||
if (escaped == 0) {
|
||||
*dstPtr++ = c;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Escape the rest, elaborating Unicode escapes when needed.
|
||||
*dstPtr++ = '\\';
|
||||
*dstPtr++ = escaped;
|
||||
if (escaped == 'u') {
|
||||
*dstPtr++ = '0';
|
||||
*dstPtr++ = '0';
|
||||
|
||||
uint8_t x = c >> 4;
|
||||
MOZ_ASSERT(x < 10);
|
||||
*dstPtr++ = '0' + x;
|
||||
|
||||
*dstPtr++ = ToLowerHex(c & 0xF);
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// Non-ASCII non-surrogates are directly copied.
|
||||
if (!unicode::IsSurrogate(c)) {
|
||||
*dstPtr++ = c;
|
||||
continue;
|
||||
}
|
||||
*dstPtr++ = '\\';
|
||||
*dstPtr++ = escaped;
|
||||
if (escaped == 'u') {
|
||||
MOZ_ASSERT(c < ' ');
|
||||
MOZ_ASSERT((c >> 4) < 10);
|
||||
uint8_t x = c >> 4, y = c % 16;
|
||||
*dstPtr++ = '0';
|
||||
*dstPtr++ = '0';
|
||||
*dstPtr++ = '0' + x;
|
||||
*dstPtr++ = y < 10 ? '0' + y : 'a' + (y - 10);
|
||||
|
||||
// So too for complete surrogate pairs.
|
||||
if (MOZ_LIKELY(unicode::IsLeadSurrogate(c) &&
|
||||
srcBegin < srcEnd &&
|
||||
unicode::IsTrailSurrogate(*srcBegin)))
|
||||
{
|
||||
*dstPtr++ = c;
|
||||
*dstPtr++ = *srcBegin++;
|
||||
continue;
|
||||
}
|
||||
|
||||
// But lone surrogates are Unicode-escaped.
|
||||
char32_t as32 = char32_t(c);
|
||||
*dstPtr++ = '\\';
|
||||
*dstPtr++ = 'u';
|
||||
*dstPtr++ = ToLowerHex(as32 >> 12);
|
||||
*dstPtr++ = ToLowerHex((as32 >> 8) & 0xF);
|
||||
*dstPtr++ = ToLowerHex((as32 >> 4) & 0xF);
|
||||
*dstPtr++ = ToLowerHex(as32 & 0xF);
|
||||
}
|
||||
|
||||
/* Steps 3-4. */
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue