Index: runtime/vm/object.cc |
=================================================================== |
--- runtime/vm/object.cc (revision 35402) |
+++ runtime/vm/object.cc (working copy) |
@@ -358,6 +358,34 @@ |
} |
+static bool IsAsciiPrintChar(int32_t code_point) { |
+ return (code_point >= ' ') && (code_point <= '~'); |
+} |
+ |
+ |
+static inline bool IsAsciiNonprintable(int32_t c) { |
+ return ((0 <= c) && (c < 32)) || (c == 127); |
+} |
+ |
+ |
+static inline bool NeedsEscapeSequence(int32_t c) { |
+ return (c == '"') || |
+ (c == '\\') || |
+ (c == '$') || |
+ IsAsciiNonprintable(c); |
+} |
+ |
+ |
+static int32_t EscapeOverhead(int32_t c) { |
+ if (IsSpecialCharacter(c)) { |
+ return 1; // 1 additional byte for the backslash. |
+ } else if (IsAsciiNonprintable(c)) { |
+ return 3; // 3 additional bytes to encode c as \x00. |
+ } |
+ return 0; |
+} |
+ |
+ |
template<typename type> |
static type SpecialCharacter(type value) { |
if (value == '"') { |
@@ -7095,7 +7123,7 @@ |
if (curr == Token::kSTRING) { |
bool escape_characters = false; |
for (intptr_t i = 0; i < literal.Length(); i++) { |
- if (IsSpecialCharacter(literal.CharAt(i))) { |
+ if (NeedsEscapeSequence(literal.CharAt(i))) { |
escape_characters = true; |
} |
} |
@@ -16256,11 +16284,6 @@ |
} |
-static bool IsAsciiPrintChar(intptr_t code_point) { |
- return code_point >= ' ' && code_point <= '~'; |
-} |
- |
- |
// Does not null-terminate. |
intptr_t String::EscapedString(char* buffer, int max_len) const { |
int pos = 0; |
@@ -16623,20 +16646,25 @@ |
if (len > 0) { |
intptr_t num_escapes = 0; |
for (intptr_t i = 0; i < len; i++) { |
- if (IsSpecialCharacter(*CharAddr(str, i))) { |
- num_escapes += 1; |
- } |
+ num_escapes += EscapeOverhead(*CharAddr(str, i)); |
} |
const String& dststr = String::Handle( |
OneByteString::New(len + num_escapes, Heap::kNew)); |
intptr_t index = 0; |
for (intptr_t i = 0; i < len; i++) { |
- if (IsSpecialCharacter(*CharAddr(str, i))) { |
- *(CharAddr(dststr, index)) = '\\'; |
- *(CharAddr(dststr, index + 1)) = SpecialCharacter(*CharAddr(str, i)); |
+ uint8_t ch = CharAt(str, i); |
+ if (IsSpecialCharacter(ch)) { |
+ SetCharAt(dststr, index, '\\'); |
+ SetCharAt(dststr, index + 1, SpecialCharacter(ch)); |
index += 2; |
+ } else if (IsAsciiNonprintable(ch)) { |
+ SetCharAt(dststr, index, '\\'); |
+ SetCharAt(dststr, index + 1, 'x'); |
+ SetCharAt(dststr, index + 2, GetHexCharacter(ch >> 4)); |
+ SetCharAt(dststr, index + 3, GetHexCharacter(ch & 0xF)); |
+ index += 4; |
} else { |
- *(CharAddr(dststr, index)) = *CharAddr(str, i); |
+ SetCharAt(dststr, index, ch); |
index += 1; |
} |
} |
@@ -16645,27 +16673,32 @@ |
return OneByteString::raw(Symbols::Empty()); |
} |
+ |
RawOneByteString* ExternalOneByteString::EscapeSpecialCharacters( |
const String& str) { |
intptr_t len = str.Length(); |
if (len > 0) { |
intptr_t num_escapes = 0; |
for (intptr_t i = 0; i < len; i++) { |
- if (IsSpecialCharacter(*CharAddr(str, i))) { |
- num_escapes += 1; |
- } |
+ num_escapes += EscapeOverhead(*CharAddr(str, i)); |
} |
const String& dststr = String::Handle( |
OneByteString::New(len + num_escapes, Heap::kNew)); |
intptr_t index = 0; |
for (intptr_t i = 0; i < len; i++) { |
- if (IsSpecialCharacter(*CharAddr(str, i))) { |
- *(OneByteString::CharAddr(dststr, index)) = '\\'; |
- *(OneByteString::CharAddr(dststr, index + 1)) = |
- SpecialCharacter(*CharAddr(str, i)); |
+ uint8_t ch = CharAt(str, i); |
+ if (IsSpecialCharacter(ch)) { |
+ OneByteString::SetCharAt(dststr, index, '\\'); |
+ OneByteString::SetCharAt(dststr, index + 1, SpecialCharacter(ch)); |
index += 2; |
+ } else if (IsAsciiNonprintable(ch)) { |
+ OneByteString::SetCharAt(dststr, index, '\\'); |
+ OneByteString::SetCharAt(dststr, index + 1, 'x'); |
+ OneByteString::SetCharAt(dststr, index + 2, GetHexCharacter(ch >> 4)); |
+ OneByteString::SetCharAt(dststr, index + 3, GetHexCharacter(ch & 0xF)); |
+ index += 4; |
} else { |
- *(OneByteString::CharAddr(dststr, index)) = *CharAddr(str, i); |
+ *(OneByteString::CharAddr(dststr, index)) = ch; |
index += 1; |
} |
} |
@@ -16886,20 +16919,25 @@ |
if (len > 0) { |
intptr_t num_escapes = 0; |
for (intptr_t i = 0; i < len; i++) { |
- if (IsSpecialCharacter(*CharAddr(str, i))) { |
- num_escapes += 1; |
- } |
+ num_escapes += EscapeOverhead(*CharAddr(str, i)); |
} |
const String& dststr = String::Handle( |
TwoByteString::New(len + num_escapes, Heap::kNew)); |
intptr_t index = 0; |
for (intptr_t i = 0; i < len; i++) { |
- if (IsSpecialCharacter(*CharAddr(str, i))) { |
- *(CharAddr(dststr, index)) = '\\'; |
- *(CharAddr(dststr, index + 1)) = SpecialCharacter(*CharAddr(str, i)); |
+ uint16_t ch = CharAt(str, i); |
+ if (IsSpecialCharacter(ch)) { |
+ SetCharAt(dststr, index, '\\'); |
+ SetCharAt(dststr, index + 1, SpecialCharacter(ch)); |
index += 2; |
+ } else if (IsAsciiNonprintable(ch)) { |
+ SetCharAt(dststr, index, '\\'); |
+ SetCharAt(dststr, index + 1, 'x'); |
+ SetCharAt(dststr, index + 2, GetHexCharacter(ch >> 4)); |
+ SetCharAt(dststr, index + 3, GetHexCharacter(ch & 0xF)); |
+ index += 4; |
} else { |
- *(CharAddr(dststr, index)) = *CharAddr(str, i); |
+ SetCharAt(dststr, index, ch); |
index += 1; |
} |
} |