This source file includes following definitions.
- QuoteIncrement
- CommentSafeIncrement
- ChunkIncrement
- end_
- GetBeforeFeature
- GetFeature
- GetAfterFeature
- SetHighlightedRegions
- Parse
- FindBounds
- FindBoundsEnd
- Parse
#include "extensions/browser/file_highlighter.h"
#include <stack>
#include "base/strings/utf_string_conversions.h"
#include "base/values.h"
namespace extensions {
namespace {
const char kBeforeHighlightKey[] = "beforeHighlight";
const char kHighlightKey[] = "highlight";
const char kAfterHighlightKey[] = "afterHighlight";
void QuoteIncrement(const std::string& str, size_t* index) {
size_t i = *index + 1;
bool found = false;
while (!found && i < str.size()) {
if (str[i] == '\\')
i += 2;
else if (str[i] == '"')
found = true;
else
++i;
}
*index = found ? i : std::string::npos;
}
void CommentSafeIncrement(const std::string& str, size_t* index) {
size_t i = *index;
if (str[i] == '/' && i + 1 < str.size()) {
if (str[i + 1] == '/') {
i += 2;
while (i < str.size() && str[i] != '\n' && str[i] != '\r')
++i;
} else if (str[i + 1] == '*') {
i += 3;
while (i < str.size() && !(str[i - 1] == '*' && str[i] == '/'))
++i;
}
}
*index = i + 1;
}
void ChunkIncrement(const std::string& str, size_t* index, size_t end) {
char c = str[*index];
std::stack<char> stack;
do {
if (c == '"')
QuoteIncrement(str, index);
else if (c == '[')
stack.push(']');
else if (c == '{')
stack.push('}');
else if (!stack.empty() && c == stack.top())
stack.pop();
CommentSafeIncrement(str, index);
c = str[*index];
} while (!stack.empty() && *index < end);
}
}
FileHighlighter::FileHighlighter(const std::string& contents)
: contents_(contents), start_(0u), end_(contents_.size()) {
}
FileHighlighter::~FileHighlighter() {
}
std::string FileHighlighter::GetBeforeFeature() const {
return contents_.substr(0, start_);
}
std::string FileHighlighter::GetFeature() const {
return contents_.substr(start_, end_ - start_);
}
std::string FileHighlighter::GetAfterFeature() const {
return contents_.substr(end_);
}
void FileHighlighter::SetHighlightedRegions(base::DictionaryValue* dict) const {
std::string before_feature = GetBeforeFeature();
if (!before_feature.empty())
dict->SetString(kBeforeHighlightKey, base::UTF8ToUTF16(before_feature));
std::string feature = GetFeature();
if (!feature.empty())
dict->SetString(kHighlightKey, base::UTF8ToUTF16(feature));
std::string after_feature = GetAfterFeature();
if (!after_feature.empty())
dict->SetString(kAfterHighlightKey, base::UTF8ToUTF16(after_feature));
}
ManifestHighlighter::ManifestHighlighter(const std::string& manifest,
const std::string& key,
const std::string& specific)
: FileHighlighter(manifest) {
start_ = contents_.find('{') + 1;
end_ = contents_.rfind('}');
Parse(key, specific);
}
ManifestHighlighter::~ManifestHighlighter() {
}
void ManifestHighlighter::Parse(const std::string& key,
const std::string& specific) {
if (FindBounds(key, true) ) {
if (!specific.empty())
FindBounds(specific, false );
size_t trim = contents_.find_last_not_of(" \t\n\r", end_ - 1);
if (trim < end_ && trim > start_)
end_ = trim + 1;
} else {
start_ = end_;
}
}
bool ManifestHighlighter::FindBounds(const std::string& feature,
bool enforce_at_top_level) {
char c = '\0';
while (start_ < end_) {
c = contents_[start_];
if (c == '"') {
size_t quote_end = start_;
QuoteIncrement(contents_, "e_end);
if (contents_.substr(start_ + 1, quote_end - 1 - start_) == feature) {
FindBoundsEnd(feature, quote_end + 1);
return true;
} else {
start_ = quote_end + 1;
}
} else if (contents_.substr(start_, feature.size()) == feature) {
FindBoundsEnd(feature, start_ + feature.size() + 1);
return true;
} else if (enforce_at_top_level && (c == '{' || c == '[')) {
ChunkIncrement(contents_, &start_, end_);
} else {
CommentSafeIncrement(contents_, &start_);
}
}
return false;
}
void ManifestHighlighter::FindBoundsEnd(const std::string& feature,
size_t local_start) {
char c = '\0';
while (local_start < end_) {
c = contents_[local_start];
if (c == ',' || c == '}' || c == ']') {
end_ = local_start;
return;
}
if (c == '"' || c == '{' || c == '[')
ChunkIncrement(contents_, &local_start, end_);
else
CommentSafeIncrement(contents_, &local_start);
}
}
SourceHighlighter::SourceHighlighter(const std::string& contents,
size_t line_number)
: FileHighlighter(contents) {
Parse(line_number);
}
SourceHighlighter::~SourceHighlighter() {
}
void SourceHighlighter::Parse(size_t line_number) {
if (line_number == 0) {
start_ = contents_.size();
return;
}
for (size_t i = 1; i < line_number; ++i) {
start_ = contents_.find('\n', start_);
if (start_ == std::string::npos)
break;
start_ += 1;
}
end_ = contents_.find('\n', start_);
start_ = start_ == std::string::npos ? contents_.size() : start_;
end_ = end_ == std::string::npos ? contents_.size() : end_;
}
}