Index: src/api.cc |
diff --git a/src/api.cc b/src/api.cc |
index b2dc2e1e943abbd81efadccc18fb6ed5c5f1c299..07f34f78ccea044eeefd5a7ee1aaf1d2cfbdda85 100644 |
--- a/src/api.cc |
+++ b/src/api.cc |
@@ -4304,6 +4304,84 @@ bool String::IsOneByte() const { |
} |
+class DefinitelyContainsOnlyOneByteHelper { |
+ public: |
+ DefinitelyContainsOnlyOneByteHelper() : is_one_byte_(true) {} |
+ bool Check(i::String* string) { |
+ i::ConsString* cons_string = i::String::VisitFlat(this, string, 0); |
+ if (cons_string == NULL) return is_one_byte_; |
+ return CheckCons(cons_string); |
+ } |
+ void VisitOneByteString(const uint8_t* chars, int length) { |
+ // Nothing to do. |
+ } |
+ void VisitTwoByteString(const uint16_t* chars, int length) { |
+ for (int i = 0; i < length; i++) { |
+ if (chars[i] >> 8) { |
+ is_one_byte_ = false; |
+ return; |
+ } |
+ } |
+ } |
+ |
+ private: |
+ bool CheckCons(i::ConsString* cons_string) { |
+ while (true) { |
+ // Check left side if flat. |
+ i::String* left = cons_string->first(); |
+ i::ConsString* left_as_cons = |
+ i::String::VisitFlat(this, left, 0); |
+ if (!is_one_byte_) return false; |
+ // Check right side if flat. |
+ i::String* right = cons_string->second(); |
+ i::ConsString* right_as_cons = |
+ i::String::VisitFlat(this, right, 0); |
+ if (!is_one_byte_) return false; |
+ // Standard recurse/iterate trick. |
+ // Falls through to the cases below for the iteration. |
+ if (left_as_cons != NULL && right_as_cons != NULL) { |
+ if (left->length() < right->length()) { |
+ CheckCons(right_as_cons); |
+ right_as_cons = NULL; |
Yang
2013/06/06 09:12:59
I think it's a bit easier to read if you just set
dcarney
2013/06/06 09:17:26
okay
|
+ } else { |
+ CheckCons(left_as_cons); |
+ left_as_cons = NULL; |
+ } |
+ // Check fast return. |
+ if (!is_one_byte_) return false; |
+ } |
+ // Descend left in place. |
+ if (left_as_cons != NULL) { |
+ cons_string = left_as_cons; |
+ continue; |
+ } |
+ // Descend right in place. |
+ if (right_as_cons != NULL) { |
+ cons_string = right_as_cons; |
+ continue; |
+ } |
+ // Terminate. |
+ break; |
+ } |
+ return is_one_byte_; |
+ } |
+ bool is_one_byte_; |
+ DISALLOW_COPY_AND_ASSIGN(DefinitelyContainsOnlyOneByteHelper); |
+}; |
+ |
+ |
+bool String::DefinitelyContainsOnlyOneByte() const { |
+ i::Handle<i::String> str = Utils::OpenHandle(this); |
+ if (IsDeadCheck(str->GetIsolate(), |
+ "v8::String::DefinitelyContainsOnlyOneByte()")) { |
+ return false; |
+ } |
+ if (str->HasOnlyOneByteChars()) return true; |
+ DefinitelyContainsOnlyOneByteHelper helper; |
+ return helper.Check(*str); |
Yang
2013/06/06 09:12:59
If we find that the string only contains one byte
dcarney
2013/06/06 09:17:26
will do
|
+} |
+ |
+ |
class Utf8LengthHelper : public i::AllStatic { |
public: |
enum State { |