Merge "AAPT2: Fix issue with parsing escape sequences when the parser only gives us part at a time"

This commit is contained in:
Adam Lesinski
2015-09-15 19:42:17 +00:00
committed by Android (Google) Code Review
5 changed files with 60 additions and 53 deletions

View File

@@ -18,11 +18,11 @@
#define AAPT_LOGGER_H
#include "Source.h"
#include "StringPiece.h"
#include <memory>
#include <ostream>
#include <string>
#include <utils/String8.h>
namespace aapt {
@@ -71,11 +71,6 @@ private:
Source mSource;
};
inline ::std::ostream& operator<<(::std::ostream& out, const std::u16string& str) {
android::String8 utf8(str.data(), str.size());
return out.write(utf8.string(), utf8.size());
}
} // namespace aapt
#endif // AAPT_LOGGER_H

View File

@@ -229,4 +229,9 @@ inline ::std::ostream& operator<<(::std::ostream& out, const BasicStringPiece<ch
} // namespace aapt
inline ::std::ostream& operator<<(::std::ostream& out, const std::u16string& str) {
android::String8 utf8(str.data(), str.size());
return out.write(utf8.string(), utf8.size());
}
#endif // AAPT_STRING_PIECE_H

View File

@@ -175,7 +175,51 @@ StringBuilder& StringBuilder::append(const StringPiece16& str) {
const char16_t* start = str.begin();
const char16_t* current = start;
while (current != end) {
if (*current == u'"') {
if (mLastCharWasEscape) {
switch (*current) {
case u't':
mStr += u'\t';
break;
case u'n':
mStr += u'\n';
break;
case u'#':
mStr += u'#';
break;
case u'@':
mStr += u'@';
break;
case u'?':
mStr += u'?';
break;
case u'"':
mStr += u'"';
break;
case u'\'':
mStr += u'\'';
break;
case u'\\':
mStr += u'\\';
break;
case u'u': {
current++;
Maybe<char16_t> c = parseUnicodeCodepoint(&current, end);
if (!c) {
mError = "invalid unicode escape sequence";
return *this;
}
mStr += c.value();
current -= 1;
break;
}
default:
// Ignore.
break;
}
mLastCharWasEscape = false;
start = current + 1;
} else if (*current == u'"') {
if (!mQuote && mTrailingSpace) {
// We found an opening quote, and we have
// trailing space, so we should append that
@@ -208,52 +252,7 @@ StringBuilder& StringBuilder::append(const StringPiece16& str) {
}
mStr.append(start, current - start);
start = current + 1;
current++;
if (current != end) {
switch (*current) {
case u't':
mStr += u'\t';
break;
case u'n':
mStr += u'\n';
break;
case u'#':
mStr += u'#';
break;
case u'@':
mStr += u'@';
break;
case u'?':
mStr += u'?';
break;
case u'"':
mStr += u'"';
break;
case u'\'':
mStr += u'\'';
break;
case u'\\':
mStr += u'\\';
break;
case u'u': {
current++;
Maybe<char16_t> c = parseUnicodeCodepoint(&current, end);
if (!c) {
mError = "invalid unicode escape sequence";
return *this;
}
mStr += c.value();
current -= 1;
break;
}
default:
// Ignore.
break;
}
start = current + 1;
}
mLastCharWasEscape = true;
} else if (!mQuote) {
// This is not quoted text, so look for whitespace.
if (isspace16(*current)) {

View File

@@ -162,6 +162,7 @@ private:
std::u16string mStr;
bool mQuote = false;
bool mTrailingSpace = false;
bool mLastCharWasEscape = false;
std::string mError;
};

View File

@@ -38,6 +38,13 @@ TEST(UtilTest, StringStartsWith) {
EXPECT_TRUE(util::stringStartsWith<char>("hello.xml", "he"));
}
TEST(UtilTest, StringBuilderSplitEscapeSequence) {
EXPECT_EQ(StringPiece16(u"this is a new\nline."),
util::StringBuilder().append(u"this is a new\\")
.append(u"nline.")
.str());
}
TEST(UtilTest, StringBuilderWhitespaceRemoval) {
EXPECT_EQ(StringPiece16(u"hey guys this is so cool"),
util::StringBuilder().append(u" hey guys ")