blob: 3735b3e841e0d15e007ca18279dabb89048fecb5 [file] [log] [blame]
/*
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "text/Unicode.h"
#include <algorithm>
#include <array>
#include "text/Utf8Iterator.h"
using ::android::StringPiece;
namespace aapt {
namespace text {
namespace {
struct CharacterProperties {
enum : uint32_t {
kXidStart = 1 << 0,
kXidContinue = 1 << 1,
};
char32_t first_char;
char32_t last_char;
uint32_t properties;
};
// Incude the generated data table.
#include "text/Unicode_data.cpp"
bool CompareCharacterProperties(const CharacterProperties& a, char32_t codepoint) {
return a.last_char < codepoint;
}
uint32_t FindCharacterProperties(char32_t codepoint) {
const auto iter_end = sCharacterProperties.end();
const auto iter = std::lower_bound(sCharacterProperties.begin(), iter_end, codepoint,
CompareCharacterProperties);
if (iter != iter_end && codepoint >= iter->first_char) {
return iter->properties;
}
return 0u;
}
} // namespace
bool IsXidStart(char32_t codepoint) {
return FindCharacterProperties(codepoint) & CharacterProperties::kXidStart;
}
bool IsXidContinue(char32_t codepoint) {
return FindCharacterProperties(codepoint) & CharacterProperties::kXidContinue;
}
// Hardcode the White_Space characters since they are few and the external/icu project doesn't
// list them as data files to parse.
// Sourced from http://www.unicode.org/Public/UCD/latest/ucd/PropList.txt
bool IsWhitespace(char32_t codepoint) {
return (codepoint >= 0x0009 && codepoint <= 0x000d) || (codepoint == 0x0020) ||
(codepoint == 0x0085) || (codepoint == 0x00a0) || (codepoint == 0x1680) ||
(codepoint >= 0x2000 && codepoint <= 0x200a) || (codepoint == 0x2028) ||
(codepoint == 0x2029) || (codepoint == 0x202f) || (codepoint == 0x205f) ||
(codepoint == 0x3000);
}
bool IsJavaIdentifier(const StringPiece& str) {
Utf8Iterator iter(str);
// Check the first character.
if (!iter.HasNext()) {
return false;
}
const char32_t first_codepoint = iter.Next();
if (!IsXidStart(first_codepoint) && first_codepoint != U'_' && first_codepoint != U'$') {
return false;
}
while (iter.HasNext()) {
const char32_t codepoint = iter.Next();
if (!IsXidContinue(codepoint) && codepoint != U'$') {
return false;
}
}
return true;
}
bool IsValidResourceEntryName(const StringPiece& str) {
Utf8Iterator iter(str);
// Check the first character.
if (!iter.HasNext()) {
return false;
}
// Resources are allowed to start with '_'
const char32_t first_codepoint = iter.Next();
if (!IsXidStart(first_codepoint) && first_codepoint != U'_') {
return false;
}
while (iter.HasNext()) {
const char32_t codepoint = iter.Next();
if (!IsXidContinue(codepoint) && codepoint != U'.' && codepoint != U'-') {
return false;
}
}
return true;
}
} // namespace text
} // namespace aapt