Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 Loading... | |
| 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 Loading... | |
| 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 int32_t String::CodePointIterator::Current() { | |
| 10550 ASSERT(index_ >= 0); | |
| 10551 ASSERT(index_ < str_.Length()); | |
| 10552 int32_t ch = str_.CharAt(index_); | |
| 10553 if (Utf16::IsLeadSurrogate(ch) && (index_ != (str_.Length() - 1))) { | |
|
siva
2012/11/19 18:25:29
Shouldn't this be (index_ < (str_.Length() - 1))
cshapiro
2012/11/19 18:55:11
Removed in the re-upload.
| |
| 10554 ASSERT(str_.IsTwoByteString()); | |
| 10555 int32_t ch2 = str_.CharAt(index_ + 1); | |
| 10556 if (Utf16::IsTrailSurrogate(ch2)) { | |
| 10557 ch = Utf16::Decode(ch, ch2); | |
| 10558 } | |
| 10559 } | |
| 10560 return ch; | |
| 10561 } | |
| 10562 | |
| 10563 | |
| 10564 bool String::CodePointIterator::Next() { | |
| 10565 ASSERT(index_ >= -1); | |
| 10566 ASSERT(index_ < str_.Length()); | |
| 10567 if (index_ == (str_.Length() - 1)) { | |
|
siva
2012/11/19 18:25:29
Why not just make this
if (index_ >= (str_.Length(
cshapiro
2012/11/19 18:55:11
I am not sure what this simplifies. Having the in
| |
| 10568 return false; | |
| 10569 } | |
| 10570 ++index_; | |
| 10571 int32_t ch2 = str_.CharAt(index_); | |
| 10572 if (Utf16::IsTrailSurrogate(ch2)) { | |
| 10573 ASSERT(str_.IsTwoByteString()); | |
| 10574 if (index_ != 0) { | |
| 10575 int32_t ch = str_.CharAt(index_ - 1); | |
| 10576 if (Utf16::IsLeadSurrogate(ch)) { | |
| 10577 if (index_ == (str_.Length() - 1)) { | |
| 10578 --index_; | |
| 10579 return false; | |
| 10580 } | |
| 10581 ++index_; | |
| 10582 } | |
|
siva
2012/11/19 18:25:29
If you structure the code as discussed offline it
| |
| 10583 } | |
| 10584 } | |
| 10585 return true; | |
| 10586 } | |
| 10587 | |
| 10588 | |
| 10548 RawOneByteString* OneByteString::EscapeSpecialCharacters(const String& str, | 10589 RawOneByteString* OneByteString::EscapeSpecialCharacters(const String& str, |
| 10549 bool raw_str) { | 10590 bool raw_str) { |
| 10550 intptr_t len = str.Length(); | 10591 intptr_t len = str.Length(); |
| 10551 if (len > 0) { | 10592 if (len > 0) { |
| 10552 intptr_t num_escapes = 0; | 10593 intptr_t num_escapes = 0; |
| 10553 intptr_t index = 0; | 10594 intptr_t index = 0; |
| 10554 for (intptr_t i = 0; i < len; i++) { | 10595 for (intptr_t i = 0; i < len; i++) { |
| 10555 if (IsSpecialCharacter(*CharAddr(str, i)) || | 10596 if (IsSpecialCharacter(*CharAddr(str, i)) || |
| 10556 (!raw_str && (*CharAddr(str, i) == '\\'))) { | 10597 (!raw_str && (*CharAddr(str, i) == '\\'))) { |
| 10557 num_escapes += 1; | 10598 num_escapes += 1; |
| (...skipping 264 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 10822 intptr_t array_len, | 10863 intptr_t array_len, |
| 10823 Heap::Space space) { | 10864 Heap::Space space) { |
| 10824 ASSERT((array_len > 0) && (utf16_len >= array_len)); | 10865 ASSERT((array_len > 0) && (utf16_len >= array_len)); |
| 10825 const String& result = String::Handle(TwoByteString::New(utf16_len, space)); | 10866 const String& result = String::Handle(TwoByteString::New(utf16_len, space)); |
| 10826 { | 10867 { |
| 10827 NoGCScope no_gc; | 10868 NoGCScope no_gc; |
| 10828 intptr_t j = 0; | 10869 intptr_t j = 0; |
| 10829 for (intptr_t i = 0; i < array_len; ++i) { | 10870 for (intptr_t i = 0; i < array_len; ++i) { |
| 10830 if (utf32_array[i] > 0xffff) { | 10871 if (utf32_array[i] > 0xffff) { |
| 10831 ASSERT(j < (utf16_len - 1)); | 10872 ASSERT(j < (utf16_len - 1)); |
| 10832 Utf8::ConvertUTF32ToUTF16(utf32_array[i], CharAddr(result, j)); | 10873 Utf16::Encode(utf32_array[i], CharAddr(result, j)); |
| 10833 j += 2; | 10874 j += 2; |
| 10834 } else { | 10875 } else { |
| 10835 ASSERT(j < utf16_len); | 10876 ASSERT(j < utf16_len); |
| 10836 *CharAddr(result, j) = utf32_array[i]; | 10877 *CharAddr(result, j) = utf32_array[i]; |
| 10837 j += 1; | 10878 j += 1; |
| 10838 } | 10879 } |
| 10839 } | 10880 } |
| 10840 } | 10881 } |
| 10841 return TwoByteString::raw(result); | 10882 return TwoByteString::raw(result); |
| 10842 } | 10883 } |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 10880 return TwoByteString::raw(result); | 10921 return TwoByteString::raw(result); |
| 10881 } | 10922 } |
| 10882 | 10923 |
| 10883 | 10924 |
| 10884 RawTwoByteString* TwoByteString::Transform(int32_t (*mapping)(int32_t ch), | 10925 RawTwoByteString* TwoByteString::Transform(int32_t (*mapping)(int32_t ch), |
| 10885 const String& str, | 10926 const String& str, |
| 10886 Heap::Space space) { | 10927 Heap::Space space) { |
| 10887 ASSERT(!str.IsNull()); | 10928 ASSERT(!str.IsNull()); |
| 10888 intptr_t len = str.Length(); | 10929 intptr_t len = str.Length(); |
| 10889 const String& result = String::Handle(TwoByteString::New(len, space)); | 10930 const String& result = String::Handle(TwoByteString::New(len, space)); |
| 10890 for (intptr_t i = 0; i < len; ++i) { | 10931 String::CodePointIterator it(str); |
| 10891 int32_t ch = mapping(str.CharAt(i)); | 10932 intptr_t i = 0; |
| 10892 ASSERT(ch >= 0 && ch <= 0xFFFF); | 10933 while (it.Next()) { |
| 10893 *CharAddr(result, i) = ch; | 10934 int32_t src = it.Current(); |
| 10935 int32_t dst = mapping(src); | |
| 10936 ASSERT(dst >= 0 && dst <= 0x10FFFF); | |
| 10937 if (dst <= 0xFFFF) { | |
| 10938 *CharAddr(result, i) = dst; | |
| 10939 i += 1; | |
| 10940 } else { | |
| 10941 Utf16::Encode(dst, CharAddr(result, i)); | |
| 10942 i += 2; | |
| 10943 } | |
| 10894 } | 10944 } |
| 10895 return TwoByteString::raw(result); | 10945 return TwoByteString::raw(result); |
| 10896 } | 10946 } |
| 10897 | 10947 |
| 10898 | 10948 |
| 10899 RawExternalOneByteString* ExternalOneByteString::New( | 10949 RawExternalOneByteString* ExternalOneByteString::New( |
| 10900 const uint8_t* data, | 10950 const uint8_t* data, |
| 10901 intptr_t len, | 10951 intptr_t len, |
| 10902 void* peer, | 10952 void* peer, |
| 10903 Dart_PeerFinalizer callback, | 10953 Dart_PeerFinalizer callback, |
| (...skipping 1182 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 12086 } | 12136 } |
| 12087 return result.raw(); | 12137 return result.raw(); |
| 12088 } | 12138 } |
| 12089 | 12139 |
| 12090 | 12140 |
| 12091 const char* WeakProperty::ToCString() const { | 12141 const char* WeakProperty::ToCString() const { |
| 12092 return "_WeakProperty"; | 12142 return "_WeakProperty"; |
| 12093 } | 12143 } |
| 12094 | 12144 |
| 12095 } // namespace dart | 12145 } // namespace dart |
| OLD | NEW |