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

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

Issue 11368138: Add some support for the code-point code-unit distinction. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: New version integrates feedback, adds less to standard String class. Created 8 years, 1 month 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
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/bigint_operations.h" 10 #include "vm/bigint_operations.h"
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after
134 // _MyClass@6b3832b.named -> _MyClass.named 134 // _MyClass@6b3832b.named -> _MyClass.named
135 // 135 //
136 static RawString* IdentifierPrettyName(const String& name) { 136 static RawString* IdentifierPrettyName(const String& name) {
137 intptr_t len = name.Length(); 137 intptr_t len = name.Length();
138 intptr_t start = 0; 138 intptr_t start = 0;
139 intptr_t at_pos = len; // Position of '@' in the name. 139 intptr_t at_pos = len; // Position of '@' in the name.
140 intptr_t dot_pos = len; // Position of '.' in the name. 140 intptr_t dot_pos = len; // Position of '.' in the name.
141 bool is_setter = false; 141 bool is_setter = false;
142 142
143 for (int i = 0; i < name.Length(); i++) { 143 for (int i = 0; i < name.Length(); i++) {
144 if (name.CharAt(i) == ':') { 144 if (name.CodeUnitAt(i) == ':') {
cshapiro 2012/11/15 20:14:51 This file is an example of why we would like the r
erikcorry 2012/11/15 23:47:05 Done.
145 ASSERT(start == 0); 145 ASSERT(start == 0);
146 if (name.CharAt(0) == 's') { 146 if (name.CodeUnitAt(0) == 's') {
147 is_setter = true; 147 is_setter = true;
148 } 148 }
149 start = i + 1; 149 start = i + 1;
150 } else if (name.CharAt(i) == '@') { 150 } else if (name.CodeUnitAt(i) == '@') {
151 ASSERT(at_pos == len); 151 ASSERT(at_pos == len);
152 at_pos = i; 152 at_pos = i;
153 } else if (name.CharAt(i) == '.') { 153 } else if (name.CodeUnitAt(i) == '.') {
154 dot_pos = i; 154 dot_pos = i;
155 break; 155 break;
156 } 156 }
157 } 157 }
158 intptr_t limit = (at_pos < dot_pos ? at_pos : dot_pos); 158 intptr_t limit = (at_pos < dot_pos ? at_pos : dot_pos);
159 if (start == 0 && limit == len) { 159 if (start == 0 && limit == len) {
160 // This name is fine as it is. 160 // This name is fine as it is.
161 return name.raw(); 161 return name.raw();
162 } 162 }
163 163
164 const String& result = 164 const String& result =
165 String::Handle(String::SubString(name, start, (limit - start))); 165 String::Handle(String::SubString(name, start, (limit - start)));
166 166
167 // Look for a second '@' now to correctly handle names like 167 // Look for a second '@' now to correctly handle names like
168 // "_ReceivePortImpl@6be832b._internal@6be832b". 168 // "_ReceivePortImpl@6be832b._internal@6be832b".
169 at_pos = len; 169 at_pos = len;
170 for (int i = dot_pos; i < name.Length(); i++) { 170 for (int i = dot_pos; i < name.Length(); i++) {
171 if (name.CharAt(i) == '@') { 171 if (name.CodeUnitAt(i) == '@') {
172 ASSERT(at_pos == len); 172 ASSERT(at_pos == len);
173 at_pos = i; 173 at_pos = i;
174 } 174 }
175 } 175 }
176 176
177 intptr_t suffix_len = at_pos - dot_pos; 177 intptr_t suffix_len = at_pos - dot_pos;
178 if (suffix_len > 1) { 178 if (suffix_len > 1) {
179 // This is a named constructor. Add the name back to the string. 179 // This is a named constructor. Add the name back to the string.
180 const String& suffix = 180 const String& suffix =
181 String::Handle(String::SubString(name, dot_pos, suffix_len)); 181 String::Handle(String::SubString(name, dot_pos, suffix_len));
(...skipping 300 matching lines...) Expand 10 before | Expand all | Expand 10 after
482 Class::NewInterface(name, script, Scanner::kDummyTokenIndex)); 482 Class::NewInterface(name, script, Scanner::kDummyTokenIndex));
483 lib.AddClass(cls); 483 lib.AddClass(cls);
484 return cls.raw(); 484 return cls.raw();
485 } 485 }
486 486
487 487
488 void Object::RegisterClass(const Class& cls, 488 void Object::RegisterClass(const Class& cls,
489 const String& name, 489 const String& name,
490 const Library& lib) { 490 const Library& lib) {
491 ASSERT(name.Length() > 0); 491 ASSERT(name.Length() > 0);
492 ASSERT(name.CharAt(0) != '_'); 492 ASSERT(name.CodeUnitAt(0) != '_');
493 cls.set_name(name); 493 cls.set_name(name);
494 lib.AddClass(cls); 494 lib.AddClass(cls);
495 } 495 }
496 496
497 497
498 void Object::RegisterPrivateClass(const Class& cls, 498 void Object::RegisterPrivateClass(const Class& cls,
499 const String& public_class_name, 499 const String& public_class_name,
500 const Library& lib) { 500 const Library& lib) {
501 ASSERT(public_class_name.Length() > 0); 501 ASSERT(public_class_name.Length() > 0);
502 ASSERT(public_class_name.CharAt(0) == '_'); 502 ASSERT(public_class_name.CodeUnitAt(0) == '_');
503 String& str = String::Handle(); 503 String& str = String::Handle();
504 str = lib.PrivateName(public_class_name); 504 str = lib.PrivateName(public_class_name);
505 cls.set_name(str); 505 cls.set_name(str);
506 lib.AddClass(cls); 506 lib.AddClass(cls);
507 } 507 }
508 508
509 509
510 RawError* Object::Init(Isolate* isolate) { 510 RawError* Object::Init(Isolate* isolate) {
511 TIMERSCOPE(time_bootstrap); 511 TIMERSCOPE(time_bootstrap);
512 ObjectStore* object_store = isolate->object_store(); 512 ObjectStore* object_store = isolate->object_store();
(...skipping 1667 matching lines...) Expand 10 before | Expand all | Expand 10 after
2180 const char* prefix, 2180 const char* prefix,
2181 intptr_t prefix_length, 2181 intptr_t prefix_length,
2182 const String& accessor_name) { 2182 const String& accessor_name) {
2183 intptr_t name_len = name.Length(); 2183 intptr_t name_len = name.Length();
2184 intptr_t accessor_name_len = accessor_name.Length(); 2184 intptr_t accessor_name_len = accessor_name.Length();
2185 2185
2186 if (name_len != (accessor_name_len + prefix_length)) { 2186 if (name_len != (accessor_name_len + prefix_length)) {
2187 return false; 2187 return false;
2188 } 2188 }
2189 for (intptr_t i = 0; i < prefix_length; i++) { 2189 for (intptr_t i = 0; i < prefix_length; i++) {
2190 if (name.CharAt(i) != prefix[i]) { 2190 if (name.CodeUnitAt(i) != static_cast<uint32_t>(prefix[i])) {
2191 return false; 2191 return false;
2192 } 2192 }
2193 } 2193 }
2194 for (intptr_t i = 0, j = prefix_length; i < accessor_name_len; i++, j++) { 2194 for (intptr_t i = 0, j = prefix_length; i < accessor_name_len; i++, j++) {
2195 if (name.CharAt(j) != accessor_name.CharAt(i)) { 2195 if (name.CodeUnitAt(j) != accessor_name.CodeUnitAt(i)) {
2196 return false; 2196 return false;
2197 } 2197 }
2198 } 2198 }
2199 return true; 2199 return true;
2200 } 2200 }
2201 2201
2202 2202
2203 RawFunction* Class::LookupFunction(const String& name) const { 2203 RawFunction* Class::LookupFunction(const String& name) const {
2204 Isolate* isolate = Isolate::Current(); 2204 Isolate* isolate = Isolate::Current();
2205 ASSERT(name.IsOneByteString()); 2205 ASSERT(name.IsOneByteString());
(...skipping 2284 matching lines...) Expand 10 before | Expand all | Expand 10 after
4490 literal = iterator.MakeLiteralToken(obj); 4490 literal = iterator.MakeLiteralToken(obj);
4491 // Advance to be able to use next token kind. 4491 // Advance to be able to use next token kind.
4492 iterator.Advance(); 4492 iterator.Advance();
4493 Token::Kind next = iterator.CurrentTokenKind(); 4493 Token::Kind next = iterator.CurrentTokenKind();
4494 4494
4495 // Handle the current token. 4495 // Handle the current token.
4496 if (curr == Token::kSTRING) { 4496 if (curr == Token::kSTRING) {
4497 bool is_raw_string = false; 4497 bool is_raw_string = false;
4498 bool escape_characters = false; 4498 bool escape_characters = false;
4499 for (intptr_t i = 0; i < literal.Length(); i++) { 4499 for (intptr_t i = 0; i < literal.Length(); i++) {
4500 if (IsSpecialCharacter(literal.CharAt(i))) { 4500 if (IsSpecialCharacter(literal.CodeUnitAt(i))) {
4501 escape_characters = true; 4501 escape_characters = true;
4502 } 4502 }
4503 // TODO(4995): Temp solution for raw strings, this will break 4503 // TODO(4995): Temp solution for raw strings, this will break
4504 // if we saw a string that is not a raw string but has back slashes 4504 // if we saw a string that is not a raw string but has back slashes
4505 // in it. 4505 // in it.
4506 if ((literal.CharAt(i) == '\\')) { 4506 if ((literal.CodeUnitAt(i) == '\\')) {
4507 if ((next != Token::kINTERPOL_VAR) && 4507 if ((next != Token::kINTERPOL_VAR) &&
4508 (next != Token::kINTERPOL_START) && 4508 (next != Token::kINTERPOL_START) &&
4509 (prev != Token::kINTERPOL_VAR) && 4509 (prev != Token::kINTERPOL_VAR) &&
4510 (prev != Token::kINTERPOL_END)) { 4510 (prev != Token::kINTERPOL_END)) {
4511 is_raw_string = true; 4511 is_raw_string = true;
4512 } else { 4512 } else {
4513 escape_characters = true; 4513 escape_characters = true;
4514 } 4514 }
4515 } 4515 }
4516 } 4516 }
4517 if ((prev != Token::kINTERPOL_VAR) && (prev != Token::kINTERPOL_END)) { 4517 if ((prev != Token::kINTERPOL_VAR) && (prev != Token::kINTERPOL_END)) {
4518 if (is_raw_string) { 4518 if (is_raw_string) {
4519 literals.Add(raw_string); 4519 literals.Add(raw_string);
4520 } 4520 }
4521 literals.Add(double_quotes); 4521 literals.Add(double_quotes);
4522 } 4522 }
4523 if (escape_characters) { 4523 if (escape_characters) {
4524 literal = String::EscapeSpecialCharacters(literal, is_raw_string); 4524 literal = String::EscapeSpecialCharacters(literal, is_raw_string);
4525 literals.Add(literal); 4525 literals.Add(literal);
4526 } else { 4526 } else {
4527 literals.Add(literal); 4527 literals.Add(literal);
4528 } 4528 }
4529 if ((next != Token::kINTERPOL_VAR) && (next != Token::kINTERPOL_START)) { 4529 if ((next != Token::kINTERPOL_VAR) && (next != Token::kINTERPOL_START)) {
4530 literals.Add(double_quotes); 4530 literals.Add(double_quotes);
4531 } 4531 }
4532 } else if (curr == Token::kINTERPOL_VAR) { 4532 } else if (curr == Token::kINTERPOL_VAR) {
4533 literals.Add(dollar); 4533 literals.Add(dollar);
4534 if (literal.CharAt(0) == Scanner::kPrivateIdentifierStart) { 4534 if (literal.CodeUnitAt(0) == Scanner::kPrivateIdentifierStart) {
4535 literal = String::SubString(literal, 0, literal.Length() - private_len); 4535 literal = String::SubString(literal, 0, literal.Length() - private_len);
4536 } 4536 }
4537 literals.Add(literal); 4537 literals.Add(literal);
4538 } else if (curr == Token::kIDENT) { 4538 } else if (curr == Token::kIDENT) {
4539 if (literal.CharAt(0) == Scanner::kPrivateIdentifierStart) { 4539 if (literal.CodeUnitAt(0) == Scanner::kPrivateIdentifierStart) {
4540 literal = String::SubString(literal, 0, literal.Length() - private_len); 4540 literal = String::SubString(literal, 0, literal.Length() - private_len);
4541 } 4541 }
4542 literals.Add(literal); 4542 literals.Add(literal);
4543 } else { 4543 } else {
4544 literals.Add(literal); 4544 literals.Add(literal);
4545 } 4545 }
4546 // Determine the separation text based on this current token. 4546 // Determine the separation text based on this current token.
4547 const String* separator = NULL; 4547 const String* separator = NULL;
4548 switch (curr) { 4548 switch (curr) {
4549 case Token::kLBRACE: 4549 case Token::kLBRACE:
(...skipping 523 matching lines...) Expand 10 before | Expand all | Expand 10 after
5073 const String& src = String::Handle(Source()); 5073 const String& src = String::Handle(Source());
5074 intptr_t current_line = 1; 5074 intptr_t current_line = 1;
5075 intptr_t line_start = -1; 5075 intptr_t line_start = -1;
5076 intptr_t last_char = -1; 5076 intptr_t last_char = -1;
5077 for (intptr_t ix = 0; 5077 for (intptr_t ix = 0;
5078 (ix < src.Length()) && (current_line <= line_number); 5078 (ix < src.Length()) && (current_line <= line_number);
5079 ix++) { 5079 ix++) {
5080 if ((current_line == line_number) && (line_start < 0)) { 5080 if ((current_line == line_number) && (line_start < 0)) {
5081 line_start = ix; 5081 line_start = ix;
5082 } 5082 }
5083 if (src.CharAt(ix) == '\n') { 5083 if (src.CodeUnitAt(ix) == '\n') {
5084 current_line++; 5084 current_line++;
5085 } else if (src.CharAt(ix) == '\r') { 5085 } else if (src.CodeUnitAt(ix) == '\r') {
5086 if ((ix + 1 != src.Length()) && (src.CharAt(ix + 1) != '\n')) { 5086 if ((ix + 1 != src.Length()) && (src.CodeUnitAt(ix + 1) != '\n')) {
5087 current_line++; 5087 current_line++;
5088 } 5088 }
5089 } else { 5089 } else {
5090 last_char = ix; 5090 last_char = ix;
5091 } 5091 }
5092 } 5092 }
5093 // Guarantee that returned string is never NULL. 5093 // Guarantee that returned string is never NULL.
5094 String& line = String::Handle(Symbols::Empty()); 5094 String& line = String::Handle(Symbols::Empty());
5095 if (line_start >= 0) { 5095 if (line_start >= 0) {
5096 line = String::SubString(src, line_start, last_char - line_start + 1); 5096 line = String::SubString(src, line_start, last_char - line_start + 1);
5097 } 5097 }
5098 return line.raw(); 5098 return line.raw();
5099 } 5099 }
5100 5100
5101 5101
5102 RawString* Script::GetSnippet(intptr_t from_line, 5102 RawString* Script::GetSnippet(intptr_t from_line,
5103 intptr_t from_column, 5103 intptr_t from_column,
5104 intptr_t to_line, 5104 intptr_t to_line,
5105 intptr_t to_column) const { 5105 intptr_t to_column) const {
5106 const String& src = String::Handle(Source()); 5106 const String& src = String::Handle(Source());
5107 intptr_t length = src.Length(); 5107 intptr_t length = src.Length();
5108 intptr_t line = 1; 5108 intptr_t line = 1;
5109 intptr_t column = 1; 5109 intptr_t column = 1;
5110 intptr_t lookahead = 0; 5110 intptr_t lookahead = 0;
5111 intptr_t snippet_start = -1; 5111 intptr_t snippet_start = -1;
5112 intptr_t snippet_end = -1; 5112 intptr_t snippet_end = -1;
5113 char c = src.CharAt(lookahead); 5113 char c = src.CodeUnitAt(lookahead);
5114 while (lookahead != length) { 5114 while (lookahead != length) {
5115 if (snippet_start == -1) { 5115 if (snippet_start == -1) {
5116 if ((line == from_line) && (column == from_column)) { 5116 if ((line == from_line) && (column == from_column)) {
5117 snippet_start = lookahead; 5117 snippet_start = lookahead;
5118 } 5118 }
5119 } else if ((line == to_line) && (column == to_column)) { 5119 } else if ((line == to_line) && (column == to_column)) {
5120 snippet_end = lookahead; 5120 snippet_end = lookahead;
5121 break; 5121 break;
5122 } 5122 }
5123 if (c == '\n') { 5123 if (c == '\n') {
5124 line++; 5124 line++;
5125 column = 0; 5125 column = 0;
5126 } 5126 }
5127 column++; 5127 column++;
5128 lookahead++; 5128 lookahead++;
5129 if (lookahead != length) { 5129 if (lookahead != length) {
5130 // Replace '\r' with '\n' and a sequence of '\r' '\n' with a single '\n'. 5130 // Replace '\r' with '\n' and a sequence of '\r' '\n' with a single '\n'.
5131 if (src.CharAt(lookahead) == '\r') { 5131 if (src.CodeUnitAt(lookahead) == '\r') {
5132 c = '\n'; 5132 c = '\n';
5133 if (lookahead + 1 != length && src.CharAt(lookahead) == '\n') { 5133 if (lookahead + 1 != length && src.CodeUnitAt(lookahead) == '\n') {
5134 lookahead++; 5134 lookahead++;
5135 } 5135 }
5136 } else { 5136 } else {
5137 c = src.CharAt(lookahead); 5137 c = src.CodeUnitAt(lookahead);
5138 } 5138 }
5139 } 5139 }
5140 } 5140 }
5141 String& snippet = String::Handle(); 5141 String& snippet = String::Handle();
5142 if ((snippet_start != -1) && (snippet_end != -1)) { 5142 if ((snippet_start != -1) && (snippet_end != -1)) {
5143 snippet = 5143 snippet =
5144 String::SubString(src, snippet_start, snippet_end - snippet_start); 5144 String::SubString(src, snippet_start, snippet_end - snippet_start);
5145 } 5145 }
5146 return snippet.raw(); 5146 return snippet.raw();
5147 } 5147 }
(...skipping 379 matching lines...) Expand 10 before | Expand all | Expand 10 after
5527 5527
5528 RawObject* Library::LookupLocalObject(const String& name) const { 5528 RawObject* Library::LookupLocalObject(const String& name) const {
5529 intptr_t index; 5529 intptr_t index;
5530 return LookupEntry(name, &index); 5530 return LookupEntry(name, &index);
5531 } 5531 }
5532 5532
5533 5533
5534 static bool ShouldBePrivate(const String& name) { 5534 static bool ShouldBePrivate(const String& name) {
5535 return 5535 return
5536 (name.Length() >= 1 && 5536 (name.Length() >= 1 &&
5537 name.CharAt(0) == '_') || 5537 name.CodeUnitAt(0) == '_') ||
5538 (name.Length() >= 5 && 5538 (name.Length() >= 5 &&
5539 (name.CharAt(4) == '_' && 5539 (name.CodeUnitAt(4) == '_' &&
5540 (name.CharAt(0) == 'g' || name.CharAt(0) == 's') && 5540 (name.CodeUnitAt(0) == 'g' || name.CodeUnitAt(0) == 's') &&
5541 name.CharAt(1) == 'e' && 5541 name.CodeUnitAt(1) == 'e' &&
5542 name.CharAt(2) == 't' && 5542 name.CodeUnitAt(2) == 't' &&
5543 name.CharAt(3) == ':')); 5543 name.CodeUnitAt(3) == ':'));
5544 } 5544 }
5545 5545
5546 5546
5547 RawField* Library::LookupFieldAllowPrivate(const String& name) const { 5547 RawField* Library::LookupFieldAllowPrivate(const String& name) const {
5548 // First check if name is found in the local scope of the library. 5548 // First check if name is found in the local scope of the library.
5549 Field& field = Field::Handle(LookupLocalField(name)); 5549 Field& field = Field::Handle(LookupLocalField(name));
5550 if (!field.IsNull()) { 5550 if (!field.IsNull()) {
5551 return field.raw(); 5551 return field.raw();
5552 } 5552 }
5553 5553
(...skipping 4294 matching lines...) Expand 10 before | Expand all | Expand 10 after
9848 return result; 9848 return result;
9849 } 9849 }
9850 9850
9851 9851
9852 intptr_t String::Hash(const String& str, intptr_t begin_index, intptr_t len) { 9852 intptr_t String::Hash(const String& str, intptr_t begin_index, intptr_t len) {
9853 ASSERT(begin_index >= 0); 9853 ASSERT(begin_index >= 0);
9854 ASSERT(len >= 0); 9854 ASSERT(len >= 0);
9855 ASSERT((begin_index + len) <= str.Length()); 9855 ASSERT((begin_index + len) <= str.Length());
9856 StringHasher hasher; 9856 StringHasher hasher;
9857 for (intptr_t i = 0; i < len; i++) { 9857 for (intptr_t i = 0; i < len; i++) {
9858 hasher.Add(str.CharAt(begin_index + i)); 9858 hasher.Add(str.CodeUnitAt(begin_index + i));
9859 } 9859 }
9860 return hasher.Finalize(String::kHashBits); 9860 return hasher.Finalize(String::kHashBits);
9861 } 9861 }
9862 9862
9863 9863
9864 template<typename T> 9864 template<typename T>
9865 static intptr_t HashImpl(const T* characters, intptr_t len) { 9865 static intptr_t HashImpl(const T* characters, intptr_t len) {
9866 ASSERT(len >= 0); 9866 ASSERT(len >= 0);
9867 StringHasher hasher; 9867 StringHasher hasher;
9868 for (intptr_t i = 0; i < len; i++) { 9868 for (intptr_t i = 0; i < len; i++) {
(...skipping 11 matching lines...) Expand all
9880 intptr_t String::Hash(const uint16_t* characters, intptr_t len) { 9880 intptr_t String::Hash(const uint16_t* characters, intptr_t len) {
9881 return HashImpl(characters, len); 9881 return HashImpl(characters, len);
9882 } 9882 }
9883 9883
9884 9884
9885 intptr_t String::Hash(const uint32_t* characters, intptr_t len) { 9885 intptr_t String::Hash(const uint32_t* characters, intptr_t len) {
9886 return HashImpl(characters, len); 9886 return HashImpl(characters, len);
9887 } 9887 }
9888 9888
9889 9889
9890 int32_t String::CharAt(intptr_t index) const { 9890 uint32_t String::CodeUnitAt(intptr_t index) const {
9891 intptr_t class_id = raw()->GetClassId(); 9891 intptr_t class_id = raw()->GetClassId();
9892 ASSERT(RawObject::IsStringClassId(class_id)); 9892 ASSERT(RawObject::IsStringClassId(class_id));
9893 NoGCScope no_gc; 9893 NoGCScope no_gc;
9894 if (class_id == kOneByteStringCid) { 9894 if (class_id == kOneByteStringCid) {
9895 return *OneByteString::CharAddr(*this, index); 9895 return OneByteString::CodeUnitAt(*this, index);
9896 } 9896 }
9897 if (class_id == kTwoByteStringCid) { 9897 if (class_id == kTwoByteStringCid) {
9898 return *TwoByteString::CharAddr(*this, index); 9898 return TwoByteString::CodeUnitAt(*this, index);
9899 } 9899 }
9900 if (class_id == kExternalOneByteStringCid) { 9900 if (class_id == kExternalOneByteStringCid) {
9901 return *ExternalOneByteString::CharAddr(*this, index); 9901 return ExternalOneByteString::CodeUnitAt(*this, index);
9902 } 9902 }
9903 ASSERT(class_id == kExternalTwoByteStringCid); 9903 ASSERT(class_id == kExternalTwoByteStringCid);
9904 return *ExternalTwoByteString::CharAddr(*this, index); 9904 return ExternalTwoByteString::CodeUnitAt(*this, index);
9905 } 9905 }
9906 9906
9907 9907
9908 intptr_t String::CharSize() const { 9908 intptr_t String::CharSize() const {
9909 intptr_t class_id = raw()->GetClassId(); 9909 intptr_t class_id = raw()->GetClassId();
9910 if (class_id == kOneByteStringCid || class_id == kExternalOneByteStringCid) { 9910 if (class_id == kOneByteStringCid || class_id == kExternalOneByteStringCid) {
9911 return kOneByteChar; 9911 return kOneByteChar;
9912 } 9912 }
9913 ASSERT(class_id == kTwoByteStringCid || 9913 ASSERT(class_id == kTwoByteStringCid ||
9914 class_id == kExternalTwoByteStringCid); 9914 class_id == kExternalTwoByteStringCid);
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
9946 9946
9947 9947
9948 bool String::Equals(const char* str) const { 9948 bool String::Equals(const char* str) const {
9949 ASSERT(str != NULL); 9949 ASSERT(str != NULL);
9950 intptr_t len = strlen(str); 9950 intptr_t len = strlen(str);
9951 for (intptr_t i = 0; i < this->Length(); ++i) { 9951 for (intptr_t i = 0; i < this->Length(); ++i) {
9952 if (*str == '\0') { 9952 if (*str == '\0') {
9953 // Lengths don't match. 9953 // Lengths don't match.
9954 return false; 9954 return false;
9955 } 9955 }
9956 int32_t ch; 9956 uint32_t ch;
9957 intptr_t consumed = Utf8::Decode(reinterpret_cast<const uint8_t*>(str), 9957 intptr_t consumed = Utf8::Decode(reinterpret_cast<const uint8_t*>(str),
9958 len, 9958 len,
9959 &ch); 9959 &ch);
9960 if (consumed == 0 || this->CharAt(i) != ch) { 9960 if (consumed == 0) return false;
9961 return false; 9961
9962 if (ch <= Utf16::kMaxCodeUnit) {
9963 if (this->CodeUnitAt(i) != ch) return false;
9964 } else {
9965 if (Utf16::CodePointAt(*this, i) != ch) return false;
9966 i++;
9962 } 9967 }
9963 str += consumed; 9968 str += consumed;
9964 len -= consumed; 9969 len -= consumed;
9965 } 9970 }
9966 return *str == '\0'; 9971 return *str == '\0';
9967 } 9972 }
9968 9973
9969 9974
9970 bool String::Equals(const uint8_t* characters, intptr_t len) const { 9975 bool String::Equals(const uint8_t* characters, intptr_t len) const {
9971 if (len != this->Length()) { 9976 if (len != this->Length()) {
9972 // Lengths don't match. 9977 // Lengths don't match.
9973 return false; 9978 return false;
9974 } 9979 }
9975 9980
9976 for (intptr_t i = 0; i < len; i++) { 9981 for (intptr_t i = 0; i < len; i++) {
9977 if (this->CharAt(i) != characters[i]) { 9982 if (this->CodeUnitAt(i) != characters[i]) {
9978 return false; 9983 return false;
9979 } 9984 }
9980 } 9985 }
9981 return true; 9986 return true;
9982 } 9987 }
9983 9988
9984 9989
9985 bool String::Equals(const uint16_t* characters, intptr_t len) const { 9990 bool String::Equals(const uint16_t* characters, intptr_t len) const {
9986 if (len != this->Length()) { 9991 if (len != this->Length()) {
9987 // Lengths don't match. 9992 // Lengths don't match.
9988 return false; 9993 return false;
9989 } 9994 }
9990 9995
9991 for (intptr_t i = 0; i < len; i++) { 9996 for (intptr_t i = 0; i < len; i++) {
9992 if (this->CharAt(i) != characters[i]) { 9997 if (this->CodeUnitAt(i) != characters[i]) {
9993 return false; 9998 return false;
9994 } 9999 }
9995 } 10000 }
9996 return true; 10001 return true;
9997 } 10002 }
9998 10003
9999 10004
10000 bool String::Equals(const uint32_t* characters, intptr_t len) const { 10005 bool String::Equals(const uint32_t* characters, intptr_t len) const {
10001 if (len != this->Length()) { 10006 if (len != this->Length()) {
10002 // Lengths don't match. 10007 // Lengths don't match.
10003 return false; 10008 return false;
10004 } 10009 }
10005 10010
10006 for (intptr_t i = 0; i < len; i++) { 10011 for (intptr_t i = 0; i < len; i++) {
10007 if (this->CharAt(i) != static_cast<int32_t>(characters[i])) { 10012 uint32_t c = this->CodeUnitAt(i);
10013 if (c != characters[i]) {
10008 return false; 10014 return false;
10009 } 10015 }
10016 if (c > Utf16::kMaxCodeUnit) i++;
10010 } 10017 }
10011 return true; 10018 return true;
10012 } 10019 }
10013 10020
10014 10021
10015 intptr_t String::CompareTo(const String& other) const { 10022 intptr_t String::CompareTo(const String& other) const {
10016 const intptr_t this_len = this->Length(); 10023 const intptr_t this_len = this->Length();
10017 const intptr_t other_len = other.IsNull() ? 0 : other.Length(); 10024 const intptr_t other_len = other.IsNull() ? 0 : other.Length();
10018 const intptr_t len = (this_len < other_len) ? this_len : other_len; 10025 const intptr_t len = (this_len < other_len) ? this_len : other_len;
10026 // UTF-16 has the high surrogate before the low surrogate so we can compare
10027 // one code unit at a time for efficiency and still get the right ordering.
10019 for (intptr_t i = 0; i < len; i++) { 10028 for (intptr_t i = 0; i < len; i++) {
10020 int32_t this_code_point = this->CharAt(i); 10029 int32_t this_code_unit = this->CodeUnitAt(i);
10021 int32_t other_code_point = other.CharAt(i); 10030 int32_t other_code_unit = other.CodeUnitAt(i);
10022 if (this_code_point < other_code_point) { 10031 if (this_code_unit < other_code_unit) {
10023 return -1; 10032 return -1;
10024 } 10033 }
10025 if (this_code_point > other_code_point) { 10034 if (this_code_unit > other_code_unit) {
10026 return 1; 10035 return 1;
10027 } 10036 }
10028 } 10037 }
10029 if (this_len < other_len) return -1; 10038 if (this_len < other_len) return -1;
10030 if (this_len > other_len) return 1; 10039 if (this_len > other_len) return 1;
10031 return 0; 10040 return 0;
10032 } 10041 }
10033 10042
10034 10043
10035 bool String::StartsWith(const String& other) const { 10044 bool String::StartsWith(const String& other) const {
10036 if (other.IsNull() || (other.Length() > this->Length())) { 10045 if (other.IsNull() || (other.Length() > this->Length())) {
10037 return false; 10046 return false;
10038 } 10047 }
10039 intptr_t slen = other.Length(); 10048 intptr_t slen = other.Length();
10040 for (int i = 0; i < slen; i++) { 10049 for (int i = 0; i < slen; i++) {
10041 if (this->CharAt(i) != other.CharAt(i)) { 10050 if (this->CodeUnitAt(i) != other.CodeUnitAt(i)) {
10042 return false; 10051 return false;
10043 } 10052 }
10044 } 10053 }
10045 return true; 10054 return true;
10046 } 10055 }
10047 10056
10048 10057
10049 RawInstance* String::Canonicalize() const { 10058 RawInstance* String::Canonicalize() const {
10050 if (IsCanonical()) { 10059 if (IsCanonical()) {
10051 return this->raw(); 10060 return this->raw();
10052 } 10061 }
10053 return Symbols::New(*this); 10062 return Symbols::New(*this);
10054 } 10063 }
10055 10064
10056 10065
10057 RawString* String::New(const char* str, Heap::Space space) { 10066 RawString* String::New(const char* str, Heap::Space space) {
10058 ASSERT(str != NULL); 10067 ASSERT(str != NULL);
10059 intptr_t array_len = strlen(str); 10068 intptr_t array_len = strlen(str);
10060 const uint8_t* utf8_array = reinterpret_cast<const uint8_t*>(str); 10069 const uint8_t* utf8_array = reinterpret_cast<const uint8_t*>(str);
10061 return String::New(utf8_array, array_len, space); 10070 return String::New(utf8_array, array_len, space);
10062 } 10071 }
10063 10072
10064 10073
10065 RawString* String::New(const uint8_t* utf8_array, 10074 RawString* String::New(const uint8_t* utf8_array,
10066 intptr_t array_len, 10075 intptr_t array_len,
10067 Heap::Space space) { 10076 Heap::Space space) {
10068 Utf8::Type type; 10077 Utf8::Type type;
10069 intptr_t len = Utf8::CodePointCount(utf8_array, array_len, &type); 10078 intptr_t len = Utf8::CodeUnitCount(utf8_array, array_len, &type);
10070 if (type == Utf8::kAscii) { 10079 if (type == Utf8::kAscii) {
10071 const String& strobj = String::Handle(OneByteString::New(len, space)); 10080 const String& strobj = String::Handle(OneByteString::New(len, space));
10072 if (len > 0) { 10081 if (len > 0) {
10073 NoGCScope no_gc; 10082 NoGCScope no_gc;
10074 Utf8::DecodeToAscii(utf8_array, array_len, 10083 Utf8::DecodeToAscii(utf8_array, array_len,
10075 OneByteString::CharAddr(strobj, 0), len); 10084 OneByteString::CharAddr(strobj, 0), len);
10076 } 10085 }
10077 return strobj.raw(); 10086 return strobj.raw();
10078 } 10087 }
10079 ASSERT((type == Utf8::kBMP) || (type == Utf8::kSMP)); 10088 ASSERT((type == Utf8::kBMP) || (type == Utf8::kSMP));
(...skipping 257 matching lines...) Expand 10 before | Expand all | Expand 10 after
10337 return Symbols::Empty(); 10346 return Symbols::Empty();
10338 } 10347 }
10339 if (begin_index > str.Length()) { 10348 if (begin_index > str.Length()) {
10340 return String::null(); 10349 return String::null();
10341 } 10350 }
10342 String& result = String::Handle(); 10351 String& result = String::Handle();
10343 bool is_one_byte_string = true; 10352 bool is_one_byte_string = true;
10344 intptr_t char_size = str.CharSize(); 10353 intptr_t char_size = str.CharSize();
10345 if (char_size == kTwoByteChar) { 10354 if (char_size == kTwoByteChar) {
10346 for (intptr_t i = begin_index; i < begin_index + length; ++i) { 10355 for (intptr_t i = begin_index; i < begin_index + length; ++i) {
10347 if (str.CharAt(i) > 0x7F) { 10356 if (str.CodeUnitAt(i) > 0x7F) {
10348 is_one_byte_string = false; 10357 is_one_byte_string = false;
10349 break; 10358 break;
10350 } 10359 }
10351 } 10360 }
10352 } 10361 }
10353 if (is_one_byte_string) { 10362 if (is_one_byte_string) {
10354 result ^= OneByteString::New(length, space); 10363 result ^= OneByteString::New(length, space);
10355 } else { 10364 } else {
10356 result ^= TwoByteString::New(length, space); 10365 result ^= TwoByteString::New(length, space);
10357 } 10366 }
(...skipping 24 matching lines...) Expand all
10382 Utf8::Encode(*this, reinterpret_cast<char*>(utf8_array), array_len); 10391 Utf8::Encode(*this, reinterpret_cast<char*>(utf8_array), array_len);
10383 } 10392 }
10384 } 10393 }
10385 10394
10386 10395
10387 RawString* String::Transform(int32_t (*mapping)(int32_t ch), 10396 RawString* String::Transform(int32_t (*mapping)(int32_t ch),
10388 const String& str, 10397 const String& str,
10389 Heap::Space space) { 10398 Heap::Space space) {
10390 ASSERT(!str.IsNull()); 10399 ASSERT(!str.IsNull());
10391 bool has_mapping = false; 10400 bool has_mapping = false;
10392 int32_t dst_max = 0; 10401 uint32_t dst_max = 0;
10393 intptr_t len = str.Length(); 10402 intptr_t len = str.Length();
10403 intptr_t out_len = 0;
10394 // TODO(cshapiro): assume a transform is required, rollback if not. 10404 // TODO(cshapiro): assume a transform is required, rollback if not.
10395 for (intptr_t i = 0; i < len; ++i) { 10405 intptr_t i = 0;
10396 int32_t src = str.CharAt(i); 10406 for (; i < len; ++i) {
10397 int32_t dst = mapping(src); 10407 uint32_t src = str.CodeUnitAt(i);
10408 if (Utf16::IsSurrogate(src)) break;
10409 uint32_t dst = mapping(src);
10398 if (src != dst) { 10410 if (src != dst) {
10399 has_mapping = true; 10411 has_mapping = true;
10400 } 10412 }
10401 dst_max = Utils::Maximum(dst_max, dst); 10413 dst_max = Utils::Maximum(dst_max, dst);
10414 out_len += dst > Utf16::kMaxCodeUnit ? 2 : 1;
10415 }
10416 for (; i < len; ++i) {
10417 uint32_t src = Utf16::CodePointAt(str, i);
10418 uint32_t dst = mapping(src);
10419 if (src != dst) {
10420 has_mapping = true;
10421 }
10422 dst_max = Utils::Maximum(dst_max, dst);
10423 out_len += dst > Utf16::kMaxCodeUnit ? 2 : 1;
10424 if (src > Utf16::kMaxCodeUnit) ++i;
10402 } 10425 }
10403 if (!has_mapping) { 10426 if (!has_mapping) {
10404 return str.raw(); 10427 return str.raw();
10405 } 10428 }
10406 if (dst_max <= 0x7F) { 10429 if (dst_max <= 0x7F) {
10407 return OneByteString::Transform(mapping, str, space); 10430 return OneByteString::Transform(mapping, str, out_len, space);
10408 } 10431 }
10409 ASSERT(dst_max > 0x7F); 10432 ASSERT(dst_max > 0x7F);
10410 return TwoByteString::Transform(mapping, str, space); 10433 return TwoByteString::Transform(mapping, str, out_len, space);
10411 } 10434 }
10412 10435
10413 10436
10414 RawString* String::ToUpperCase(const String& str, Heap::Space space) { 10437 RawString* String::ToUpperCase(const String& str, Heap::Space space) {
10415 // TODO(cshapiro): create a fast-path for OneByteString instances. 10438 // TODO(cshapiro): create a fast-path for OneByteString instances.
10416 return Transform(CaseMapping::ToUpper, str, space); 10439 return Transform(CaseMapping::ToUpper, str, space);
10417 } 10440 }
10418 10441
10419 10442
10420 RawString* String::ToLowerCase(const String& str, Heap::Space space) { 10443 RawString* String::ToLowerCase(const String& str, Heap::Space space) {
(...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after
10607 intptr_t str_len = str.Length(); 10630 intptr_t str_len = str.Length();
10608 String::Copy(result, pos, str, 0, str_len); 10631 String::Copy(result, pos, str, 0, str_len);
10609 pos += str_len; 10632 pos += str_len;
10610 } 10633 }
10611 return OneByteString::raw(result); 10634 return OneByteString::raw(result);
10612 } 10635 }
10613 10636
10614 10637
10615 RawOneByteString* OneByteString::Transform(int32_t (*mapping)(int32_t ch), 10638 RawOneByteString* OneByteString::Transform(int32_t (*mapping)(int32_t ch),
10616 const String& str, 10639 const String& str,
10640 int out_length,
10617 Heap::Space space) { 10641 Heap::Space space) {
10618 ASSERT(!str.IsNull()); 10642 ASSERT(!str.IsNull());
10619 intptr_t len = str.Length(); 10643 intptr_t len = str.Length();
10620 const String& result = String::Handle(OneByteString::New(len, space)); 10644 const String& result =
10621 for (intptr_t i = 0; i < len; ++i) { 10645 String::Handle(OneByteString::New(out_length, space));
10622 int32_t ch = mapping(str.CharAt(i)); 10646 for (intptr_t i = 0, j = 0; i < len; ++i, j++) {
10623 ASSERT(ch >= 0 && ch <= 0x7F); 10647 uint32_t old_ch = str.CodeUnitAt(i);
10624 *CharAddr(result, i) = ch; 10648 if (old_ch > Utf16::kMaxCodeUnit) i++;
10649 uint32_t ch = mapping(old_ch);
10650 ASSERT(ch <= 0x7Fu);
10651 *CharAddr(result, j) = ch;
10625 } 10652 }
10626 return OneByteString::raw(result); 10653 return OneByteString::raw(result);
10627 } 10654 }
10628 10655
10629 10656
10630 RawTwoByteString* TwoByteString::EscapeSpecialCharacters(const String& str, 10657 RawTwoByteString* TwoByteString::EscapeSpecialCharacters(const String& str,
10631 bool raw_str) { 10658 bool raw_str) {
10632 intptr_t len = str.Length(); 10659 intptr_t len = str.Length();
10633 if (len > 0) { 10660 if (len > 0) {
10634 intptr_t num_escapes = 0; 10661 intptr_t num_escapes = 0;
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
10698 RawTwoByteString* TwoByteString::New(intptr_t utf16_len, 10725 RawTwoByteString* TwoByteString::New(intptr_t utf16_len,
10699 const uint32_t* utf32_array, 10726 const uint32_t* utf32_array,
10700 intptr_t array_len, 10727 intptr_t array_len,
10701 Heap::Space space) { 10728 Heap::Space space) {
10702 ASSERT((array_len > 0) && (utf16_len >= array_len)); 10729 ASSERT((array_len > 0) && (utf16_len >= array_len));
10703 const String& result = String::Handle(TwoByteString::New(utf16_len, space)); 10730 const String& result = String::Handle(TwoByteString::New(utf16_len, space));
10704 { 10731 {
10705 NoGCScope no_gc; 10732 NoGCScope no_gc;
10706 intptr_t j = 0; 10733 intptr_t j = 0;
10707 for (intptr_t i = 0; i < array_len; ++i) { 10734 for (intptr_t i = 0; i < array_len; ++i) {
10708 if (utf32_array[i] > 0xffff) { 10735 uint32_t code_point = utf32_array[i];
10736 if (code_point > Utf16::kMaxCodeUnit) {
10709 ASSERT(j < (utf16_len - 1)); 10737 ASSERT(j < (utf16_len - 1));
10710 Utf8::ConvertUTF32ToUTF16(utf32_array[i], CharAddr(result, j)); 10738 *CharAddr(result, j) = Utf16::LeadFromCodePoint(code_point);
10739 *CharAddr(result, j + 1) = Utf16::TrailFromCodePoint(code_point);
10711 j += 2; 10740 j += 2;
10712 } else { 10741 } else {
10713 ASSERT(j < utf16_len); 10742 ASSERT(j < utf16_len);
10714 *CharAddr(result, j) = utf32_array[i]; 10743 *CharAddr(result, j) = utf32_array[i];
10715 j += 1; 10744 j += 1;
10716 } 10745 }
10717 } 10746 }
10718 } 10747 }
10719 return TwoByteString::raw(result); 10748 return TwoByteString::raw(result);
10720 } 10749 }
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
10754 intptr_t str_len = str.Length(); 10783 intptr_t str_len = str.Length();
10755 String::Copy(result, pos, str, 0, str_len); 10784 String::Copy(result, pos, str, 0, str_len);
10756 pos += str_len; 10785 pos += str_len;
10757 } 10786 }
10758 return TwoByteString::raw(result); 10787 return TwoByteString::raw(result);
10759 } 10788 }
10760 10789
10761 10790
10762 RawTwoByteString* TwoByteString::Transform(int32_t (*mapping)(int32_t ch), 10791 RawTwoByteString* TwoByteString::Transform(int32_t (*mapping)(int32_t ch),
10763 const String& str, 10792 const String& str,
10793 int out_length,
10764 Heap::Space space) { 10794 Heap::Space space) {
10765 ASSERT(!str.IsNull()); 10795 ASSERT(!str.IsNull());
10766 intptr_t len = str.Length(); 10796 intptr_t len = str.Length();
10767 const String& result = String::Handle(TwoByteString::New(len, space)); 10797 const String& result =
10768 for (intptr_t i = 0; i < len; ++i) { 10798 String::Handle(TwoByteString::New(out_length, space));
10769 int32_t ch = mapping(str.CharAt(i)); 10799 for (intptr_t i = 0, j = 0; i < len; ++i, j++) {
10770 ASSERT(ch >= 0 && ch <= 0xFFFF); 10800 uint32_t old_ch = Utf16::CodePointAt(str, i);
10771 *CharAddr(result, i) = ch; 10801 if (old_ch > Utf16::kMaxCodeUnit) i++;
10802 uint32_t ch = mapping(old_ch);
10803 ASSERT(ch <= Utf16::kMaxCodePoint);
10804 if (ch <= Utf16::kMaxCodeUnit) {
10805 *CharAddr(result, j) = ch;
10806 } else {
10807 *CharAddr(result, j) = Utf16::LeadFromCodePoint(ch);
10808 *CharAddr(result, j + 1) = Utf16::TrailFromCodePoint(ch);
10809 ++j;
10810 }
10811 ASSERT(j <= out_length);
10772 } 10812 }
10773 return TwoByteString::raw(result); 10813 return TwoByteString::raw(result);
10774 } 10814 }
10775 10815
10776 10816
10777 static void AddFinalizer(const Object& referent, 10817 static void AddFinalizer(const Object& referent,
10778 void* peer, 10818 void* peer,
10779 Dart_WeakPersistentHandleFinalizer callback) { 10819 Dart_WeakPersistentHandleFinalizer callback) {
10780 ASSERT(callback != NULL); 10820 ASSERT(callback != NULL);
10781 ApiState* state = Isolate::Current()->api_state(); 10821 ApiState* state = Isolate::Current()->api_state();
(...skipping 1221 matching lines...) Expand 10 before | Expand all | Expand 10 after
12003 } 12043 }
12004 return result.raw(); 12044 return result.raw();
12005 } 12045 }
12006 12046
12007 12047
12008 const char* WeakProperty::ToCString() const { 12048 const char* WeakProperty::ToCString() const {
12009 return "_WeakProperty"; 12049 return "_WeakProperty";
12010 } 12050 }
12011 12051
12012 } // namespace dart 12052 } // namespace dart
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698