mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-10-25 00:27:29 +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. */
|
/* Step 1. */
|
||||||
*dstPtr++ = '"';
|
*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. */
|
/* Step 2. */
|
||||||
while (srcBegin != srcEnd) {
|
while (srcBegin != srcEnd) {
|
||||||
SrcCharT c = *srcBegin++;
|
const SrcCharT c = *srcBegin++;
|
||||||
size_t escapeIndex = c % sizeof(escapeLookup);
|
|
||||||
Latin1Char escaped = escapeLookup[escapeIndex];
|
// Handle the Latin-1 cases.
|
||||||
if (MOZ_LIKELY((escapeIndex != size_t(c)) || !escaped)) {
|
if (MOZ_LIKELY(c < sizeof(escapeLookup))) {
|
||||||
|
Latin1Char escaped = escapeLookup[c];
|
||||||
|
|
||||||
|
// Directly copy non-escaped code points.
|
||||||
|
if (escaped == 0) {
|
||||||
*dstPtr++ = c;
|
*dstPtr++ = c;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Escape the rest, elaborating Unicode escapes when needed.
|
||||||
*dstPtr++ = '\\';
|
*dstPtr++ = '\\';
|
||||||
*dstPtr++ = escaped;
|
*dstPtr++ = escaped;
|
||||||
if (escaped == 'u') {
|
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';
|
*dstPtr++ = '0';
|
||||||
|
|
||||||
|
uint8_t x = c >> 4;
|
||||||
|
MOZ_ASSERT(x < 10);
|
||||||
*dstPtr++ = '0' + x;
|
*dstPtr++ = '0' + x;
|
||||||
*dstPtr++ = y < 10 ? '0' + y : 'a' + (y - 10);
|
|
||||||
|
*dstPtr++ = ToLowerHex(c & 0xF);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Non-ASCII non-surrogates are directly copied.
|
||||||
|
if (!unicode::IsSurrogate(c)) {
|
||||||
|
*dstPtr++ = c;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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. */
|
/* Steps 3-4. */
|
||||||
|
|
|
||||||
|
|
@ -466,6 +466,19 @@ IsTrailSurrogate(uint32_t codePoint)
|
||||||
return codePoint >= TrailSurrogateMin && codePoint <= TrailSurrogateMax;
|
return codePoint >= TrailSurrogateMin && codePoint <= TrailSurrogateMax;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if the given value is a UTF-16 surrogate.
|
||||||
|
*
|
||||||
|
* This function is intended for use in contexts where 32-bit values may need
|
||||||
|
* to be tested to see if they reside in the surrogate range, so it doesn't
|
||||||
|
* just take char16_t.
|
||||||
|
*/
|
||||||
|
inline bool
|
||||||
|
IsSurrogate(uint32_t codePoint)
|
||||||
|
{
|
||||||
|
return LeadSurrogateMin <= codePoint && codePoint <= TrailSurrogateMax;
|
||||||
|
}
|
||||||
|
|
||||||
inline char16_t
|
inline char16_t
|
||||||
LeadSurrogate(uint32_t codePoint)
|
LeadSurrogate(uint32_t codePoint)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue