Reviewers: Vitaly Repeshko, antonm,
Message:
At the request of v8 users who want to be able to opt out from null
termination
when using String::Write(), String::WriteAscii() and String::WriteUtf8().
See
this thread:
http://code.google.com/p/v8/issues/detail?id=1537&can=3&colspec=ID%20Type%20Status%20Priority%20Owner%20Summary%20HW%20OS%20Area%20Stars
Chromium does not appear to be affected by this change as calls to these
methods
omit the last argument and use the default value. It compiles perfectly
fine.
Not sure about other projects that depend on v8.
Description:
Slight API change enabling opting out from null termination in
String::Write*().
BUG=v8:1537
TEST=cctest test-api/StringWrite
Please review this at http://codereview.chromium.org/7706002/
SVN Base: https://v8.googlecode.com/svn/branches/bleeding_edge
Affected files:
M include/v8.h
M src/api.cc
M test/cctest/test-api.cc
Index: include/v8.h
diff --git a/include/v8.h b/include/v8.h
index
46e4f0db0e3a6478605e2a02943dd994c468cb48..751d56914feb0c5cdfad5fa61ecc48363f21485b
100644
--- a/include/v8.h
+++ b/include/v8.h
@@ -1039,29 +1039,30 @@ class String : public Primitive {
* \param length The number of characters to copy from the string. For
* WriteUtf8 the number of bytes in the buffer.
* \param nchars_ref The number of characters written, can be NULL.
- * \param hints Various hints that might affect performance of this or
+ * \param options Various hints that might affect performance of this or
* subsequent operations.
* \return The number of characters copied to the buffer excluding the
null
* terminator. For WriteUtf8: The number of bytes copied to the
buffer
- * including the null terminator.
+ * including the null terminator (if written).
*/
enum WriteHints {
- NO_HINTS = 0,
- HINT_MANY_WRITES_EXPECTED = 1
+ NO_OPTIONS = 0,
+ MANY_WRITES_EXPECTED = 1,
+ WRITE_NO_NULL_TERMINATION = 2
};
V8EXPORT int Write(uint16_t* buffer,
int start = 0,
int length = -1,
- WriteHints hints = NO_HINTS) const; // UTF-16
+ int options = NO_OPTIONS) const; // UTF-16
V8EXPORT int WriteAscii(char* buffer,
int start = 0,
int length = -1,
- WriteHints hints = NO_HINTS) const; // ASCII
+ int options = NO_OPTIONS) const; // ASCII
V8EXPORT int WriteUtf8(char* buffer,
int length = -1,
int* nchars_ref = NULL,
- WriteHints hints = NO_HINTS) const; // UTF-8
+ int options = NO_OPTIONS) const; // UTF-8
/**
* A zero length string.
Index: src/api.cc
diff --git a/src/api.cc b/src/api.cc
index
f6291163bf1b77a4c3b1ff225b4ac38c2d069af5..5728a547e2bd2dc399b3dc66847bddc0bce427c5
100644
--- a/src/api.cc
+++ b/src/api.cc
@@ -3621,7 +3621,7 @@ int String::Utf8Length() const {
int String::WriteUtf8(char* buffer,
int capacity,
int* nchars_ref,
- WriteHints hints) const {
+ int options) const {
i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
if (IsDeadCheck(isolate, "v8::String::WriteUtf8()")) return 0;
LOG_API(isolate, "String::WriteUtf8");
@@ -3629,7 +3629,7 @@ int String::WriteUtf8(char* buffer,
i::StringInputBuffer& write_input_buffer =
*isolate->write_input_buffer();
i::Handle<i::String> str = Utils::OpenHandle(this);
isolate->string_tracker()->RecordWrite(str);
- if (hints & HINT_MANY_WRITES_EXPECTED) {
+ if (options & MANY_WRITES_EXPECTED) {
// Flatten the string for efficiency. This applies whether we are
// using StringInputBuffer or Get(i) to access the characters.
str->TryFlatten();
@@ -3669,7 +3669,8 @@ int String::WriteUtf8(char* buffer,
}
}
if (nchars_ref != NULL) *nchars_ref = nchars;
- if (i == len && (capacity == -1 || pos < capacity))
+ if (!(options & WRITE_NO_NULL_TERMINATION) &&
+ (i == len && (capacity == -1 || pos < capacity)))
buffer[pos++] = '\0';
return pos;
}
@@ -3678,7 +3679,7 @@ int String::WriteUtf8(char* buffer,
int String::WriteAscii(char* buffer,
int start,
int length,
- WriteHints hints) const {
+ int options) const {
i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
if (IsDeadCheck(isolate, "v8::String::WriteAscii()")) return 0;
LOG_API(isolate, "String::WriteAscii");
@@ -3687,7 +3688,7 @@ int String::WriteAscii(char* buffer,
ASSERT(start >= 0 && length >= -1);
i::Handle<i::String> str = Utils::OpenHandle(this);
isolate->string_tracker()->RecordWrite(str);
- if (hints & HINT_MANY_WRITES_EXPECTED) {
+ if (options & MANY_WRITES_EXPECTED) {
// Flatten the string for efficiency. This applies whether we are
// using StringInputBuffer or Get(i) to access the characters.
str->TryFlatten();
@@ -3703,7 +3704,7 @@ int String::WriteAscii(char* buffer,
if (c == '\0') c = ' ';
buffer[i] = c;
}
- if (length == -1 || i < length)
+ if (!(options & WRITE_NO_NULL_TERMINATION) && (length == -1 || i <
length))
buffer[i] = '\0';
return i;
}
@@ -3712,7 +3713,7 @@ int String::WriteAscii(char* buffer,
int String::Write(uint16_t* buffer,
int start,
int length,
- WriteHints hints) const {
+ int options) const {
i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
if (IsDeadCheck(isolate, "v8::String::Write()")) return 0;
LOG_API(isolate, "String::Write");
@@ -3720,7 +3721,7 @@ int String::Write(uint16_t* buffer,
ASSERT(start >= 0 && length >= -1);
i::Handle<i::String> str = Utils::OpenHandle(this);
isolate->string_tracker()->RecordWrite(str);
- if (hints & HINT_MANY_WRITES_EXPECTED) {
+ if (options & MANY_WRITES_EXPECTED) {
// Flatten the string for efficiency. This applies whether we are
// using StringInputBuffer or Get(i) to access the characters.
str->TryFlatten();
@@ -3730,7 +3731,8 @@ int String::Write(uint16_t* buffer,
end = str->length();
if (end < 0) return 0;
i::String::WriteToFlat(*str, buffer, start, end);
- if (length == -1 || end - start < length) {
+ if (!(options & WRITE_NO_NULL_TERMINATION) &&
+ (length == -1 || end - start < length)) {
buffer[end - start] = '\0';
}
return end - start;
Index: test/cctest/test-api.cc
diff --git a/test/cctest/test-api.cc b/test/cctest/test-api.cc
index
e206bb9ac366f3ed1ade216406cf9914410b6ca0..cd3e0873032173392c77122a95282fe08380de6e
100644
--- a/test/cctest/test-api.cc
+++ b/test/cctest/test-api.cc
@@ -5296,6 +5296,40 @@ THREADED_TEST(StringWrite) {
CHECK_EQ(0, strncmp("d\1", buf, 2));
uint16_t answer7[] = {'d', 0x101};
CHECK_EQ(0, StrNCmp16(answer7, wbuf, 2));
+
+ memset(wbuf, 0x1, sizeof(wbuf));
+ wbuf[5] = 'X';
+ len = str->Write(wbuf, 0, 6, String::WRITE_NO_NULL_TERMINATION);
+ CHECK_EQ(5, len);
+ CHECK_EQ('X', wbuf[5]);
+ uint16_t answer8a[] = {'a', 'b', 'c', 'd', 'e'};
+ uint16_t answer8b[] = {'a', 'b', 'c', 'd', 'e', '\0'};
+ CHECK_EQ(0, StrNCmp16(answer8a, wbuf, 5));
+ CHECK_NE(0, StrCmp16(answer8b, wbuf));
+ wbuf[5] = '\0';
+ CHECK_EQ(0, StrCmp16(answer8b, wbuf));
+
+ memset(buf, 0x1, sizeof(buf));
+ buf[5] = 'X';
+ len = str->WriteAscii(buf, 0, 6, String::WRITE_NO_NULL_TERMINATION);
+ CHECK_EQ(5, len);
+ CHECK_EQ('X', buf[5]);
+ CHECK_EQ(0, strncmp("abcde", buf, 5));
+ CHECK_NE(0, strcmp("abcde", buf));
+ buf[5] = '\0';
+ CHECK_EQ(0, strcmp("abcde", buf));
+
+ memset(utf8buf, 0x1, sizeof(utf8buf));
+ utf8buf[8] = 'X';
+ len = str2->WriteUtf8(utf8buf, sizeof(utf8buf), &charlen,
+ String::WRITE_NO_NULL_TERMINATION);
+ CHECK_EQ(8, len);
+ CHECK_EQ('X', utf8buf[8]);
+ CHECK_EQ(5, charlen);
+ CHECK_EQ(0, strncmp(utf8buf, "abc\303\260\342\230\203", 8));
+ CHECK_NE(0, strcmp(utf8buf, "abc\303\260\342\230\203"));
+ utf8buf[8] = '\0';
+ CHECK_EQ(0, strcmp(utf8buf, "abc\303\260\342\230\203"));
}
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev