Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(164)

Side by Side Diff: runtime/vm/object.cc

Issue 542363003: Don't double-escape in strings in the VM Service, and don't use \u0000 to determine the string lengt (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: build Created 6 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « runtime/vm/object.h ('k') | runtime/vm/object_test.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 #include "vm/object.h" 5 #include "vm/object.h"
6 6
7 #include "include/dart_api.h" 7 #include "include/dart_api.h"
8 #include "platform/assert.h" 8 #include "platform/assert.h"
9 #include "vm/assembler.h" 9 #include "vm/assembler.h"
10 #include "vm/cpu.h" 10 #include "vm/cpu.h"
(...skipping 346 matching lines...) Expand 10 before | Expand all | Expand 10 after
357 (value == '\f') || 357 (value == '\f') ||
358 (value == '\b') || 358 (value == '\b') ||
359 (value == '\t') || 359 (value == '\t') ||
360 (value == '\v') || 360 (value == '\v') ||
361 (value == '\r') || 361 (value == '\r') ||
362 (value == '\\') || 362 (value == '\\') ||
363 (value == '$')); 363 (value == '$'));
364 } 364 }
365 365
366 366
367 static bool IsAsciiPrintChar(int32_t code_point) {
368 return (code_point >= ' ') && (code_point <= '~');
369 }
370
371
372 static inline bool IsAsciiNonprintable(int32_t c) { 367 static inline bool IsAsciiNonprintable(int32_t c) {
373 return ((0 <= c) && (c < 32)) || (c == 127); 368 return ((0 <= c) && (c < 32)) || (c == 127);
374 } 369 }
375 370
376 371
377 static inline bool NeedsEscapeSequence(int32_t c) { 372 static inline bool NeedsEscapeSequence(int32_t c) {
378 return (c == '"') || 373 return (c == '"') ||
379 (c == '\\') || 374 (c == '\\') ||
380 (c == '$') || 375 (c == '$') ||
381 IsAsciiNonprintable(c); 376 IsAsciiNonprintable(c);
(...skipping 16760 matching lines...) Expand 10 before | Expand all | Expand 10 after
17142 result = OneByteString::New(length, space); 17137 result = OneByteString::New(length, space);
17143 } else { 17138 } else {
17144 result = TwoByteString::New(length, space); 17139 result = TwoByteString::New(length, space);
17145 } 17140 }
17146 String::Copy(result, 0, str, begin_index, length); 17141 String::Copy(result, 0, str, begin_index, length);
17147 return result.raw(); 17142 return result.raw();
17148 } 17143 }
17149 17144
17150 17145
17151 const char* String::ToCString() const { 17146 const char* String::ToCString() const {
17147 intptr_t length;
17148 return ToCString(&length);
17149 }
17150
17151
17152 const char* String::ToCString(intptr_t* length) const {
17152 if (IsOneByteString()) { 17153 if (IsOneByteString()) {
17153 // Quick conversion if OneByteString contains only ASCII characters. 17154 // Quick conversion if OneByteString contains only ASCII characters.
17154 intptr_t len = Length(); 17155 intptr_t len = Length();
17155 if (len == 0) { 17156 if (len == 0) {
17157 *length = 0;
17156 return ""; 17158 return "";
17157 } 17159 }
17158 Zone* zone = Isolate::Current()->current_zone(); 17160 Zone* zone = Isolate::Current()->current_zone();
17159 uint8_t* result = zone->Alloc<uint8_t>(len + 1); 17161 uint8_t* result = zone->Alloc<uint8_t>(len + 1);
17160 NoGCScope no_gc; 17162 NoGCScope no_gc;
17161 const uint8_t* original_str = OneByteString::CharAddr(*this, 0); 17163 const uint8_t* original_str = OneByteString::CharAddr(*this, 0);
17162 for (intptr_t i = 0; i < len; i++) { 17164 for (intptr_t i = 0; i < len; i++) {
17163 if (original_str[i] <= Utf8::kMaxOneByteChar) { 17165 if (original_str[i] <= Utf8::kMaxOneByteChar) {
17164 result[i] = original_str[i]; 17166 result[i] = original_str[i];
17165 } else { 17167 } else {
17166 len = -1; 17168 len = -1;
17167 break; 17169 break;
17168 } 17170 }
17169 } 17171 }
17170 if (len > 0) { 17172 if (len > 0) {
17171 result[len] = 0; 17173 result[len] = 0;
17174 *length = len;
17172 return reinterpret_cast<const char*>(result); 17175 return reinterpret_cast<const char*>(result);
17173 } 17176 }
17174 } 17177 }
17175 const intptr_t len = Utf8::Length(*this); 17178 const intptr_t len = Utf8::Length(*this);
17176 Zone* zone = Isolate::Current()->current_zone(); 17179 Zone* zone = Isolate::Current()->current_zone();
17177 uint8_t* result = zone->Alloc<uint8_t>(len + 1); 17180 uint8_t* result = zone->Alloc<uint8_t>(len + 1);
17178 ToUTF8(result, len); 17181 ToUTF8(result, len);
17179 result[len] = 0; 17182 result[len] = 0;
17183 *length = len;
17180 return reinterpret_cast<const char*>(result); 17184 return reinterpret_cast<const char*>(result);
17181 } 17185 }
17182 17186
17183 17187
17184 // Does not null-terminate. 17188 const char* String::ToCStringTruncated(intptr_t max_len,
17185 intptr_t String::EscapedString(char* buffer, int max_len) const { 17189 bool* did_truncate,
17186 int pos = 0; 17190 intptr_t* length) const {
17191 if (Length() <= max_len) {
17192 *did_truncate = false;
17193 return ToCString(length);
17194 }
17187 17195
17188 CodePointIterator cpi(*this); 17196 intptr_t aligned_limit = max_len;
17189 while (cpi.Next()) { 17197 if (Utf16::IsLeadSurrogate(CharAt(max_len - 1))) {
17190 int32_t code_point = cpi.Current(); 17198 // Don't let truncation split a surrogate pair.
17191 if (IsSpecialCharacter(code_point)) { 17199 aligned_limit--;
17192 if (pos + 2 > max_len) {
17193 return pos;
17194 }
17195 buffer[pos++] = '\\';
17196 buffer[pos++] = SpecialCharacter(code_point);
17197 } else if (IsAsciiPrintChar(code_point)) {
17198 buffer[pos++] = code_point;
17199 } else {
17200 if (pos + 6 > max_len) {
17201 return pos;
17202 }
17203 pos += OS::SNPrint((buffer + pos), (max_len - pos),
17204 "\\u%04x", code_point);
17205 }
17206 if (pos == max_len) {
17207 return pos;
17208 }
17209 } 17200 }
17210 return pos; 17201 ASSERT(!Utf16::IsLeadSurrogate(CharAt(aligned_limit - 1)));
17202
17203 *did_truncate = true;
17204 const String& truncated =
17205 String::Handle(String::SubString(*this, 0, aligned_limit));
17206 return truncated.ToCString(length);
17211 } 17207 }
17212 17208
17213 17209
17214 intptr_t String::EscapedStringLen(intptr_t too_long) const {
17215 intptr_t len = 0;
17216
17217 CodePointIterator cpi(*this);
17218 while (cpi.Next()) {
17219 int32_t code_point = cpi.Current();
17220 if (IsSpecialCharacter(code_point)) {
17221 len += 2; // e.g. "\n"
17222 } else if (IsAsciiPrintChar(code_point)) {
17223 len += 1;
17224 } else {
17225 len += 6; // e.g. "\u0000".
17226 }
17227 if (len > too_long) {
17228 // No point going further.
17229 break;
17230 }
17231 }
17232 return len;
17233 }
17234
17235
17236 const char* String::ToUserCString(intptr_t max_len) const {
17237 // Compute the needed length for the buffer.
17238 const intptr_t escaped_len = EscapedStringLen(max_len);
17239 intptr_t print_len = escaped_len;
17240 intptr_t buffer_len = escaped_len + 2; // +2 for quotes.
17241 if (buffer_len > max_len) {
17242 buffer_len = max_len; // Truncate.
17243 print_len = max_len - 5; // -2 for quotes, -3 for elipsis.
17244 }
17245
17246 // Allocate the buffer.
17247 Zone* zone = Isolate::Current()->current_zone();
17248 char* buffer = zone->Alloc<char>(buffer_len + 1);
17249
17250 // Leading quote.
17251 intptr_t pos = 0;
17252 buffer[pos++] = '\"';
17253
17254 // Print escaped string.
17255 pos += EscapedString((buffer + pos), print_len);
17256
17257 // Trailing quote.
17258 buffer[pos++] = '\"';
17259
17260 if (print_len < escaped_len) {
17261 buffer[pos++] = '.';
17262 buffer[pos++] = '.';
17263 buffer[pos++] = '.';
17264 }
17265 ASSERT(pos <= buffer_len);
17266 buffer[pos++] = '\0';
17267
17268 return buffer;
17269 }
17270
17271
17272 void String::PrintJSONImpl(JSONStream* stream, bool ref) const { 17210 void String::PrintJSONImpl(JSONStream* stream, bool ref) const {
17273 JSONObject jsobj(stream); 17211 JSONObject jsobj(stream);
17274 if (raw() == Symbols::OptimizedOut().raw()) { 17212 if (raw() == Symbols::OptimizedOut().raw()) {
17275 // TODO(turnidge): This is a hack. The user could have this 17213 // TODO(turnidge): This is a hack. The user could have this
17276 // special string in their program. Fixing this involves updating 17214 // special string in their program. Fixing this involves updating
17277 // the debugging api a bit. 17215 // the debugging api a bit.
17278 jsobj.AddProperty("type", "Sentinel"); 17216 jsobj.AddProperty("type", "Sentinel");
17279 jsobj.AddProperty("id", "objects/optimized-out"); 17217 jsobj.AddProperty("id", "objects/optimized-out");
17280 jsobj.AddProperty("valueAsString", "<optimized out>"); 17218 jsobj.AddProperty("valueAsString", "<optimized out>");
17281 return; 17219 return;
17282 } 17220 }
17283 AddTypeProperties(&jsobj, "String", JSONType(), ref); 17221 AddTypeProperties(&jsobj, "String", JSONType(), ref);
17284 PrintSharedInstanceJSON(&jsobj, ref); 17222 PrintSharedInstanceJSON(&jsobj, ref);
17285 ObjectIdRing* ring = Isolate::Current()->object_id_ring(); 17223 ObjectIdRing* ring = Isolate::Current()->object_id_ring();
17286 const intptr_t id = ring->GetIdForObject(raw()); 17224 const intptr_t id = ring->GetIdForObject(raw());
17287 jsobj.AddPropertyF("id", "objects/%" Pd "", id); 17225 jsobj.AddPropertyF("id", "objects/%" Pd "", id);
17288 jsobj.AddProperty("valueAsString", ToUserCString(1024)); 17226 if (ref) {
17227 bool did_truncate = false;
17228 intptr_t length = 0;
17229 const char* cstr = ToCStringTruncated(128, &did_truncate, &length);
17230 jsobj.AddProperty("valueAsString", cstr, length);
17231 if (did_truncate) {
17232 jsobj.AddProperty("valueAsStringIsTruncated", did_truncate);
17233 }
17234 } else {
17235 intptr_t length = 0;
17236 const char* cstr = ToCString(&length);
17237 jsobj.AddProperty("valueAsString", cstr, length);
17238 }
17289 } 17239 }
17290 17240
17291 17241
17292 void String::ToUTF8(uint8_t* utf8_array, intptr_t array_len) const { 17242 void String::ToUTF8(uint8_t* utf8_array, intptr_t array_len) const {
17293 ASSERT(array_len >= Utf8::Length(*this)); 17243 ASSERT(array_len >= Utf8::Length(*this));
17294 Utf8::Encode(*this, reinterpret_cast<char*>(utf8_array), array_len); 17244 Utf8::Encode(*this, reinterpret_cast<char*>(utf8_array), array_len);
17295 } 17245 }
17296 17246
17297 17247
17298 static FinalizablePersistentHandle* AddFinalizer( 17248 static FinalizablePersistentHandle* AddFinalizer(
(...skipping 2495 matching lines...) Expand 10 before | Expand all | Expand 10 after
19794 return tag_label.ToCString(); 19744 return tag_label.ToCString();
19795 } 19745 }
19796 19746
19797 19747
19798 void UserTag::PrintJSONImpl(JSONStream* stream, bool ref) const { 19748 void UserTag::PrintJSONImpl(JSONStream* stream, bool ref) const {
19799 Instance::PrintJSONImpl(stream, ref); 19749 Instance::PrintJSONImpl(stream, ref);
19800 } 19750 }
19801 19751
19802 19752
19803 } // namespace dart 19753 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/object.h ('k') | runtime/vm/object_test.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698