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

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

Issue 11416054: Provide a code point iterator to the String class to simplify iteration. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: address review comments 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
« 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/bigint_operations.h" 10 #include "vm/bigint_operations.h"
(...skipping 9972 matching lines...) Expand 10 before | Expand all | Expand 10 after
9983 9983
9984 const String& other_string = String::Cast(other); 9984 const String& other_string = String::Cast(other);
9985 if (this->HasHash() && other_string.HasHash() && 9985 if (this->HasHash() && other_string.HasHash() &&
9986 (this->Hash() != other_string.Hash())) { 9986 (this->Hash() != other_string.Hash())) {
9987 return false; // Both sides have a hash code and it does not match. 9987 return false; // Both sides have a hash code and it does not match.
9988 } 9988 }
9989 return Equals(other_string, 0, other_string.Length()); 9989 return Equals(other_string, 0, other_string.Length());
9990 } 9990 }
9991 9991
9992 9992
9993 bool String::Equals(const char* str) const { 9993 bool String::Equals(const char* utf8_array) const {
9994 ASSERT(str != NULL); 9994 ASSERT(utf8_array != NULL);
9995 intptr_t len = strlen(str); 9995 intptr_t len = strlen(utf8_array);
9996 for (intptr_t i = 0; i < this->Length(); ++i) { 9996 for (intptr_t i = 0; i < this->Length(); ++i) {
9997 if (*str == '\0') { 9997 if (*utf8_array == '\0') {
9998 // Lengths don't match. 9998 // Lengths don't match.
9999 return false; 9999 return false;
10000 } 10000 }
10001 int32_t ch; 10001 int32_t ch;
10002 intptr_t consumed = Utf8::Decode(reinterpret_cast<const uint8_t*>(str), 10002 intptr_t consumed = Utf8::Decode(
10003 len, 10003 reinterpret_cast<const uint8_t*>(utf8_array),
10004 &ch); 10004 len,
10005 &ch);
10005 if (consumed == 0 || this->CharAt(i) != ch) { 10006 if (consumed == 0 || this->CharAt(i) != ch) {
10006 return false; 10007 return false;
10007 } 10008 }
10008 str += consumed; 10009 utf8_array += consumed;
10009 len -= consumed; 10010 len -= consumed;
10010 } 10011 }
10011 return *str == '\0'; 10012 return *utf8_array == '\0';
10012 } 10013 }
10013 10014
10014 10015
10015 bool String::Equals(const uint8_t* characters, intptr_t len) const { 10016 bool String::Equals(const uint8_t* latin1_array, intptr_t len) const {
10016 if (len != this->Length()) { 10017 if (len != this->Length()) {
10017 // Lengths don't match. 10018 // Lengths don't match.
10018 return false; 10019 return false;
10019 } 10020 }
10020 10021
10021 for (intptr_t i = 0; i < len; i++) { 10022 for (intptr_t i = 0; i < len; i++) {
10022 if (this->CharAt(i) != characters[i]) { 10023 if (this->CharAt(i) != latin1_array[i]) {
10023 return false; 10024 return false;
10024 } 10025 }
10025 } 10026 }
10026 return true; 10027 return true;
10027 } 10028 }
10028 10029
10029 10030
10030 bool String::Equals(const uint16_t* characters, intptr_t len) const { 10031 bool String::Equals(const uint16_t* utf16_array, intptr_t len) const {
10031 if (len != this->Length()) { 10032 if (len != this->Length()) {
10032 // Lengths don't match. 10033 // Lengths don't match.
10033 return false; 10034 return false;
10034 } 10035 }
10035 10036
10036 for (intptr_t i = 0; i < len; i++) { 10037 for (intptr_t i = 0; i < len; i++) {
10037 if (this->CharAt(i) != characters[i]) { 10038 if (this->CharAt(i) != utf16_array[i]) {
10038 return false; 10039 return false;
10039 } 10040 }
10040 } 10041 }
10041 return true; 10042 return true;
10042 } 10043 }
10043 10044
10044 10045
10045 bool String::Equals(const uint32_t* characters, intptr_t len) const { 10046 bool String::Equals(const uint32_t* utf32_array, intptr_t len) const {
10046 if (len != this->Length()) { 10047 CodePointIterator it(*this);
10047 // Lengths don't match. 10048 intptr_t i = 0;
10048 return false; 10049 while (it.Next()) {
10049 } 10050 if (it.Current() != static_cast<int32_t>(utf32_array[i])) {
10050
10051 for (intptr_t i = 0; i < len; i++) {
10052 if (this->CharAt(i) != static_cast<int32_t>(characters[i])) {
10053 return false; 10051 return false;
10054 } 10052 }
10053 ++i;
10054 }
10055 if (i != len) {
10056 return false;
10055 } 10057 }
10056 return true; 10058 return true;
10057 } 10059 }
10058 10060
10059 10061
10060 intptr_t String::CompareTo(const String& other) const { 10062 intptr_t String::CompareTo(const String& other) const {
10061 const intptr_t this_len = this->Length(); 10063 const intptr_t this_len = this->Length();
10062 const intptr_t other_len = other.IsNull() ? 0 : other.Length(); 10064 const intptr_t other_len = other.IsNull() ? 0 : other.Length();
10063 const intptr_t len = (this_len < other_len) ? this_len : other_len; 10065 const intptr_t len = (this_len < other_len) ? this_len : other_len;
10064 for (intptr_t i = 0; i < len; i++) { 10066 for (intptr_t i = 0; i < len; i++) {
(...skipping 440 matching lines...) Expand 10 before | Expand all | Expand 10 after
10505 return this->raw(); 10507 return this->raw();
10506 } 10508 }
10507 10509
10508 10510
10509 RawString* String::Transform(int32_t (*mapping)(int32_t ch), 10511 RawString* String::Transform(int32_t (*mapping)(int32_t ch),
10510 const String& str, 10512 const String& str,
10511 Heap::Space space) { 10513 Heap::Space space) {
10512 ASSERT(!str.IsNull()); 10514 ASSERT(!str.IsNull());
10513 bool has_mapping = false; 10515 bool has_mapping = false;
10514 int32_t dst_max = 0; 10516 int32_t dst_max = 0;
10515 intptr_t len = str.Length(); 10517 CodePointIterator it(str);
10516 // TODO(cshapiro): assume a transform is required, rollback if not. 10518 while (it.Next()) {
10517 for (intptr_t i = 0; i < len; ++i) { 10519 int32_t src = it.Current();
10518 int32_t src = str.CharAt(i);
10519 int32_t dst = mapping(src); 10520 int32_t dst = mapping(src);
10520 if (src != dst) { 10521 if (src != dst) {
10521 has_mapping = true; 10522 has_mapping = true;
10522 } 10523 }
10523 dst_max = Utils::Maximum(dst_max, dst); 10524 dst_max = Utils::Maximum(dst_max, dst);
10524 } 10525 }
10525 if (!has_mapping) { 10526 if (!has_mapping) {
10526 return str.raw(); 10527 return str.raw();
10527 } 10528 }
10528 if (dst_max <= 0xFF) { 10529 if (dst_max <= 0xFF) {
10529 return OneByteString::Transform(mapping, str, space); 10530 return OneByteString::Transform(mapping, str, space);
10530 } 10531 }
10531 ASSERT(dst_max > 0xFF); 10532 ASSERT(dst_max > 0xFF);
10532 return TwoByteString::Transform(mapping, str, space); 10533 return TwoByteString::Transform(mapping, str, space);
10533 } 10534 }
10534 10535
10535 10536
10536 RawString* String::ToUpperCase(const String& str, Heap::Space space) { 10537 RawString* String::ToUpperCase(const String& str, Heap::Space space) {
10537 // TODO(cshapiro): create a fast-path for OneByteString instances. 10538 // TODO(cshapiro): create a fast-path for OneByteString instances.
10538 return Transform(CaseMapping::ToUpper, str, space); 10539 return Transform(CaseMapping::ToUpper, str, space);
10539 } 10540 }
10540 10541
10541 10542
10542 RawString* String::ToLowerCase(const String& str, Heap::Space space) { 10543 RawString* String::ToLowerCase(const String& str, Heap::Space space) {
10543 // TODO(cshapiro): create a fast-path for OneByteString instances. 10544 // TODO(cshapiro): create a fast-path for OneByteString instances.
10544 return Transform(CaseMapping::ToLower, str, space); 10545 return Transform(CaseMapping::ToLower, str, space);
10545 } 10546 }
10546 10547
10547 10548
10549 bool String::CodePointIterator::Next() {
10550 ASSERT(index_ >= -1);
10551 ASSERT(index_ < str_.Length());
10552 int d = (ch_ <= 0xFFFF) ? 1 : 2;
siva 2012/11/19 19:29:54 (ch_ <= Utf16::kMaxBmpCodePoint)
cshapiro 2012/11/19 19:47:59 I'll fix that before submitting. I think we shoul
10553 if (index_ == (str_.Length() - d)) {
10554 return false;
10555 }
10556 index_ += d;
10557 ch_ = str_.CharAt(index_);
10558 if (Utf16::IsLeadSurrogate(ch_) && (index_ != (str_.Length() - 1))) {
10559 int32_t ch2 = str_.CharAt(index_ + 1);
10560 if (Utf16::IsTrailSurrogate(ch2)) {
10561 ch_ = Utf16::Decode(ch_, ch2);
10562 }
10563 }
10564 return true;
10565 }
10566
10567
10548 RawOneByteString* OneByteString::EscapeSpecialCharacters(const String& str, 10568 RawOneByteString* OneByteString::EscapeSpecialCharacters(const String& str,
10549 bool raw_str) { 10569 bool raw_str) {
10550 intptr_t len = str.Length(); 10570 intptr_t len = str.Length();
10551 if (len > 0) { 10571 if (len > 0) {
10552 intptr_t num_escapes = 0; 10572 intptr_t num_escapes = 0;
10553 intptr_t index = 0; 10573 intptr_t index = 0;
10554 for (intptr_t i = 0; i < len; i++) { 10574 for (intptr_t i = 0; i < len; i++) {
10555 if (IsSpecialCharacter(*CharAddr(str, i)) || 10575 if (IsSpecialCharacter(*CharAddr(str, i)) ||
10556 (!raw_str && (*CharAddr(str, i) == '\\'))) { 10576 (!raw_str && (*CharAddr(str, i) == '\\'))) {
10557 num_escapes += 1; 10577 num_escapes += 1;
(...skipping 264 matching lines...) Expand 10 before | Expand all | Expand 10 after
10822 intptr_t array_len, 10842 intptr_t array_len,
10823 Heap::Space space) { 10843 Heap::Space space) {
10824 ASSERT((array_len > 0) && (utf16_len >= array_len)); 10844 ASSERT((array_len > 0) && (utf16_len >= array_len));
10825 const String& result = String::Handle(TwoByteString::New(utf16_len, space)); 10845 const String& result = String::Handle(TwoByteString::New(utf16_len, space));
10826 { 10846 {
10827 NoGCScope no_gc; 10847 NoGCScope no_gc;
10828 intptr_t j = 0; 10848 intptr_t j = 0;
10829 for (intptr_t i = 0; i < array_len; ++i) { 10849 for (intptr_t i = 0; i < array_len; ++i) {
10830 if (utf32_array[i] > 0xffff) { 10850 if (utf32_array[i] > 0xffff) {
10831 ASSERT(j < (utf16_len - 1)); 10851 ASSERT(j < (utf16_len - 1));
10832 Utf8::ConvertUTF32ToUTF16(utf32_array[i], CharAddr(result, j)); 10852 Utf16::Encode(utf32_array[i], CharAddr(result, j));
10833 j += 2; 10853 j += 2;
10834 } else { 10854 } else {
10835 ASSERT(j < utf16_len); 10855 ASSERT(j < utf16_len);
10836 *CharAddr(result, j) = utf32_array[i]; 10856 *CharAddr(result, j) = utf32_array[i];
10837 j += 1; 10857 j += 1;
10838 } 10858 }
10839 } 10859 }
10840 } 10860 }
10841 return TwoByteString::raw(result); 10861 return TwoByteString::raw(result);
10842 } 10862 }
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
10880 return TwoByteString::raw(result); 10900 return TwoByteString::raw(result);
10881 } 10901 }
10882 10902
10883 10903
10884 RawTwoByteString* TwoByteString::Transform(int32_t (*mapping)(int32_t ch), 10904 RawTwoByteString* TwoByteString::Transform(int32_t (*mapping)(int32_t ch),
10885 const String& str, 10905 const String& str,
10886 Heap::Space space) { 10906 Heap::Space space) {
10887 ASSERT(!str.IsNull()); 10907 ASSERT(!str.IsNull());
10888 intptr_t len = str.Length(); 10908 intptr_t len = str.Length();
10889 const String& result = String::Handle(TwoByteString::New(len, space)); 10909 const String& result = String::Handle(TwoByteString::New(len, space));
10890 for (intptr_t i = 0; i < len; ++i) { 10910 String::CodePointIterator it(str);
10891 int32_t ch = mapping(str.CharAt(i)); 10911 intptr_t i = 0;
10892 ASSERT(ch >= 0 && ch <= 0xFFFF); 10912 while (it.Next()) {
10893 *CharAddr(result, i) = ch; 10913 int32_t src = it.Current();
10914 int32_t dst = mapping(src);
10915 ASSERT(dst >= 0 && dst <= 0x10FFFF);
10916 if (dst <= 0xFFFF) {
10917 *CharAddr(result, i) = dst;
10918 i += 1;
10919 } else {
10920 Utf16::Encode(dst, CharAddr(result, i));
10921 i += 2;
10922 }
10894 } 10923 }
10895 return TwoByteString::raw(result); 10924 return TwoByteString::raw(result);
10896 } 10925 }
10897 10926
10898 10927
10899 RawExternalOneByteString* ExternalOneByteString::New( 10928 RawExternalOneByteString* ExternalOneByteString::New(
10900 const uint8_t* data, 10929 const uint8_t* data,
10901 intptr_t len, 10930 intptr_t len,
10902 void* peer, 10931 void* peer,
10903 Dart_PeerFinalizer callback, 10932 Dart_PeerFinalizer callback,
(...skipping 1182 matching lines...) Expand 10 before | Expand all | Expand 10 after
12086 } 12115 }
12087 return result.raw(); 12116 return result.raw();
12088 } 12117 }
12089 12118
12090 12119
12091 const char* WeakProperty::ToCString() const { 12120 const char* WeakProperty::ToCString() const {
12092 return "_WeakProperty"; 12121 return "_WeakProperty";
12093 } 12122 }
12094 12123
12095 } // namespace dart 12124 } // 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