Chromium Code Reviews| Index: runtime/vm/object.cc |
| =================================================================== |
| --- runtime/vm/object.cc (revision 31037) |
| +++ runtime/vm/object.cc (working copy) |
| @@ -11403,7 +11403,7 @@ |
| } |
| -const char* Instance::ToUserCString(intptr_t maxLen) const { |
| +const char* Instance::ToUserCString(intptr_t max_len, intptr_t nesting) const { |
| if (raw() == Object::sentinel().raw()) { |
| return "<not initialized>"; |
| } else if (raw() == Object::transition_sentinel().raw()) { |
| @@ -14235,33 +14235,34 @@ |
| } |
| -static bool IsAsciiPrintChar(intptr_t codePoint) { |
| - return codePoint >= ' ' && codePoint <= '~'; |
| +static bool IsAsciiPrintChar(intptr_t code_point) { |
| + return code_point >= ' ' && code_point <= '~'; |
| } |
| // Does not null-terminate. |
| -intptr_t String::EscapedString(char* buffer, int maxLen) const { |
| +intptr_t String::EscapedString(char* buffer, int max_len) const { |
| int pos = 0; |
| CodePointIterator cpi(*this); |
| while (cpi.Next()) { |
| - int32_t codePoint = cpi.Current(); |
| - if (IsSpecialCharacter(codePoint)) { |
| - if (pos + 2 > maxLen) { |
| + int32_t code_point = cpi.Current(); |
| + if (IsSpecialCharacter(code_point)) { |
| + if (pos + 2 > max_len) { |
| return pos; |
| } |
| buffer[pos++] = '\\'; |
| - buffer[pos++] = SpecialCharacter(codePoint); |
| - } else if (IsAsciiPrintChar(codePoint)) { |
| - buffer[pos++] = codePoint; |
| + buffer[pos++] = SpecialCharacter(code_point); |
| + } else if (IsAsciiPrintChar(code_point)) { |
| + buffer[pos++] = code_point; |
| } else { |
| - if (pos + 6 > maxLen) { |
| + if (pos + 6 > max_len) { |
| return pos; |
| } |
| - pos += OS::SNPrint((buffer + pos), (maxLen - pos), "\\u%04x", codePoint); |
| + pos += OS::SNPrint((buffer + pos), (max_len - pos), |
| + "\\u%04x", code_point); |
| } |
| - if (pos == maxLen) { |
| + if (pos == max_len) { |
| return pos; |
| } |
| } |
| @@ -14269,20 +14270,20 @@ |
| } |
| -intptr_t String::EscapedStringLen(intptr_t tooLong) const { |
| +intptr_t String::EscapedStringLen(intptr_t too_long) const { |
| intptr_t len = 0; |
| CodePointIterator cpi(*this); |
| while (cpi.Next()) { |
| - int32_t codePoint = cpi.Current(); |
| - if (IsSpecialCharacter(codePoint)) { |
| + int32_t code_point = cpi.Current(); |
| + if (IsSpecialCharacter(code_point)) { |
| len += 2; // e.g. "\n" |
| - } else if (IsAsciiPrintChar(codePoint)) { |
| + } else if (IsAsciiPrintChar(code_point)) { |
| len += 1; |
| } else { |
| len += 6; // e.g. "\u0000". |
| } |
| - if (len > tooLong) { |
| + if (len > too_long) { |
| // No point going further. |
| break; |
| } |
| @@ -14291,36 +14292,36 @@ |
| } |
| -const char* String::ToUserCString(intptr_t maxLen) const { |
| +const char* String::ToUserCString(intptr_t max_len, intptr_t nesting) const { |
| // Compute the needed length for the buffer. |
| - const intptr_t escapedLen = EscapedStringLen(maxLen); |
| - intptr_t printLen = escapedLen; |
| - intptr_t bufferLen = escapedLen + 2; // +2 for quotes. |
| - if (bufferLen > maxLen) { |
| - bufferLen = maxLen; // Truncate. |
| - printLen = maxLen - 5; // -2 for quotes, -3 for elipsis. |
| + const intptr_t escaped_len = EscapedStringLen(max_len); |
| + intptr_t print_len = escaped_len; |
| + intptr_t buffer_len = escaped_len + 2; // +2 for quotes. |
| + if (buffer_len > max_len) { |
| + buffer_len = max_len; // Truncate. |
| + print_len = max_len - 5; // -2 for quotes, -3 for elipsis. |
| } |
| // Allocate the buffer. |
| Zone* zone = Isolate::Current()->current_zone(); |
| - char* buffer = zone->Alloc<char>(bufferLen + 1); |
| + char* buffer = zone->Alloc<char>(buffer_len + 1); |
| // Leading quote. |
| intptr_t pos = 0; |
| buffer[pos++] = '\"'; |
| // Print escaped string. |
| - pos += EscapedString((buffer + pos), printLen); |
| + pos += EscapedString((buffer + pos), print_len); |
| // Trailing quote. |
| buffer[pos++] = '\"'; |
| - if (printLen < escapedLen) { |
| + if (print_len < escaped_len) { |
| buffer[pos++] = '.'; |
| buffer[pos++] = '.'; |
| buffer[pos++] = '.'; |
| } |
| - ASSERT(pos <= bufferLen); |
| + ASSERT(pos <= buffer_len); |
| buffer[pos++] = '\0'; |
| return buffer; |
| @@ -15383,6 +15384,106 @@ |
| } |
| +const char* GrowableObjectArray::ToUserCString(intptr_t max_len, |
| + intptr_t nesting) const { |
| + if (Length() == 0) { |
| + return "[]"; |
| + } |
| + if (nesting > 3) { |
| + return "[...]"; |
| + } |
| + |
| + Isolate* isolate = Isolate::Current(); |
| + Zone* zone = isolate->current_zone(); |
| + Object& obj = Object::Handle(isolate); |
| + Instance& element = Instance::Handle(isolate); |
| + |
| + // Pre-print the suffix that we will use if the string is truncated. |
| + // It is important to know the suffix length when deciding where to |
| + // limit the list. |
| + char trunc_suffix[16]; |
|
Cutch
2013/12/13 19:22:46
const intptr_t kTruncSuffixLen = 16;
turnidge
2013/12/13 19:29:58
Done.
|
| + intptr_t trunc_suffix_len; |
| + if (nesting == 0) { |
| + trunc_suffix_len = OS::SNPrint(trunc_suffix, 16, "...](length:%" Pd ")", |
| + Length()); |
| + } else { |
| + trunc_suffix_len = OS::SNPrint(trunc_suffix, 16, "...]"); |
| + } |
| + bool truncate = false; |
| + |
| + const int kMaxPrintElements = 128; |
| + const char* strings[kMaxPrintElements]; |
| + intptr_t print_len = 1; // +1 for "[" |
| + |
| + // Figure out how many elements will fit in the string. |
| + int i = 0; |
| + while (i < Length()) { |
| + if (i == kMaxPrintElements) { |
| + if (i < Length()) { |
| + truncate = true; |
| + } |
| + break; |
| + } |
| + obj = At(i); |
| + if (!obj.IsInstance()) { |
| + // Bail. |
| + UNREACHABLE(); |
| + return "[<invalid list>]"; |
| + } |
| + element ^= obj.raw(); |
| + |
| + // Choose max child length. This is chosen so that it is small |
| + // enough to maybe fit but not so small that we can't print |
| + // anything. |
| + int child_max_len = max_len - print_len; |
| + if ((i + 1) < Length()) { |
| + child_max_len -= (trunc_suffix_len + 1); // 1 for "," |
| + } else { |
| + child_max_len -= 1; // 1 for "]" |
| + } |
| + if (child_max_len < 8) { |
| + child_max_len = 8; |
| + } |
| + |
| + strings[i] = element.ToUserCString(child_max_len, nesting + 1); |
| + print_len += strlen(strings[i]) + 1; // +1 for "," or "]" |
| + i++; |
| + if (print_len > max_len) { |
| + truncate = true; |
| + break; |
| + } |
| + } |
| + if (truncate) { |
| + // Go backwards until there is enough room for the truncation suffix. |
| + while (i >= 0 && (print_len + trunc_suffix_len) > max_len) { |
| + i--; |
| + print_len -= (strlen(strings[i]) + 1); // +1 for "," |
| + } |
| + } |
| + |
| + // Finally, allocate and print the string. |
| + int num_to_print = i; |
| + char* buffer = zone->Alloc<char>(print_len + 1); // +1 for "\0" |
| + intptr_t pos = 0; |
| + buffer[pos++] = '['; |
| + for (i = 0; i < num_to_print; i++) { |
| + if ((i + 1) == Length()) { |
| + pos += OS::SNPrint((buffer + pos), (max_len + 1 - pos), |
| + "%s]", strings[i]); |
| + } else { |
| + pos += OS::SNPrint((buffer + pos), (max_len + 1 - pos), |
| + "%s,", strings[i]); |
| + } |
| + } |
| + if (i < Length()) { |
| + pos += OS::SNPrint((buffer + pos), (max_len + 1 - pos), "%s", trunc_suffix); |
| + } |
| + ASSERT(pos <= max_len); |
| + buffer[pos] = '\0'; |
| + return buffer; |
| +} |
| + |
| + |
| void GrowableObjectArray::PrintToJSONStream(JSONStream* stream, |
| bool ref) const { |
| Instance::PrintToJSONStream(stream, ref); |