Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 66ea8400 authored by Adam Lesinski's avatar Adam Lesinski
Browse files

AAPT2: Accept Java unicode identifiers

Test: make aapt2_tests
Change-Id: I75a0e52d43b1785001bfe120eea7484f7bb4682b
parent 46307b11
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -111,11 +111,12 @@ cc_library_host_static {
        "proto/TableProtoDeserializer.cpp",
        "proto/TableProtoSerializer.cpp",
        "split/TableSplitter.cpp",
        "text/Unicode.cpp",
        "text/Utf8Iterator.cpp",
        "unflatten/BinaryResourceParser.cpp",
        "unflatten/ResChunkPullParser.cpp",
        "util/BigBuffer.cpp",
        "util/Files.cpp",
        "util/Utf8Iterator.cpp",
        "util/Util.cpp",
        "ConfigDescription.cpp",
        "Debug.cpp",
+14 −13
Original line number Diff line number Diff line
@@ -15,20 +15,24 @@
 */

#include "ResourceTable.h"
#include "ConfigDescription.h"
#include "NameMangler.h"
#include "ResourceValues.h"
#include "ValueVisitor.h"
#include "util/Util.h"

#include <android-base/logging.h>
#include <androidfw/ResourceTypes.h>
#include <algorithm>
#include <memory>
#include <string>
#include <tuple>

using android::StringPiece;
#include "android-base/logging.h"
#include "androidfw/ResourceTypes.h"

#include "ConfigDescription.h"
#include "NameMangler.h"
#include "ResourceValues.h"
#include "ValueVisitor.h"
#include "text/Unicode.h"
#include "util/Util.h"

using ::aapt::text::IsValidResourceEntryName;
using ::android::StringPiece;

namespace aapt {

@@ -283,12 +287,9 @@ ResourceTable::CollisionResult ResourceTable::ResolveValueCollision(Value* exist
  return CollisionResult::kConflict;
}

static constexpr const char* kValidNameChars = "._-";

static StringPiece ValidateName(const StringPiece& name) {
  auto iter = util::FindNonAlphaNumericAndNotInSet(name, kValidNameChars);
  if (iter != name.end()) {
    return StringPiece(iter, 1);
  if (!IsValidResourceEntryName(name)) {
    return name;
  }
  return {};
}
+114 −0
Original line number Diff line number Diff line
/*
 * 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;
}

bool IsJavaIdentifier(const StringPiece& str) {
  Utf8Iterator iter(str);

  // Check the first character.
  if (!iter.HasNext()) {
    return false;
  }

  if (!IsXidStart(iter.Next())) {
    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
+54 −0
Original line number Diff line number Diff line
/*
 * 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.
 */

#ifndef AAPT_TEXT_UNICODE_H
#define AAPT_TEXT_UNICODE_H

#include "androidfw/StringPiece.h"

namespace aapt {
namespace text {

// Returns true if the Unicode codepoint has the XID_Start property, meaning it can be used as the
// first character of a programming language identifier.
// http://unicode.org/reports/tr31/#Default_Identifier_Syntax
//
// XID_Start is a Unicode Derived Core Property. It is a variation of the ID_Start
// Derived Core Property, accounting for a few characters that, when normalized, yield valid
// characters in the ID_Start set.
bool IsXidStart(char32_t codepoint);

// Returns true if the Unicode codepoint has the XID_Continue property, meaning it can be used in
// any position of a programming language identifier, except the first.
// http://unicode.org/reports/tr31/#Default_Identifier_Syntax
//
// XID_Continue is a Unicode Derived Core Property. It is a variation of the ID_Continue
// Derived Core Property, accounting for a few characters that, when normalized, yield valid
// characters in the ID_Continue set.
bool IsXidContinue(char32_t codepoint);

// Returns true if the UTF8 string can be used as a Java identifier.
// NOTE: This does not check against the set of reserved Java keywords.
bool IsJavaIdentifier(const android::StringPiece& str);

// Returns true if the UTF8 string can be used as the entry name of a resource name.
// This is the `entry` part of package:type/entry.
bool IsValidResourceEntryName(const android::StringPiece& str);

}  // namespace text
}  // namespace aapt

#endif  // AAPT_TEXT_UNICODE_H
+629 −0

File added.

Preview size limit exceeded, changes collapsed.

Loading