in resources/src/main/java/org/robolectric/res/android/ResTable.java [1140:1259]
public int identifierForName(String nameString, String type, String packageName,
final Ref<Integer> outTypeSpecFlags) {
// if (kDebugTableSuperNoisy) {
// printf("Identifier for name: error=%d\n", mError);
// }
// // Check for internal resource identifier as the very first thing, so
// // that we will always find them even when there are no resources.
if (nameString.startsWith("^")) {
if (sInternalNameToIdMap.containsKey(nameString)) {
if (outTypeSpecFlags != null) {
outTypeSpecFlags.set(ResTable_typeSpec.SPEC_PUBLIC);
}
return sInternalNameToIdMap.get(nameString);
}
if (nameString.length() > 7)
if (nameString.substring(1, 6).equals("index_")) {
int index = Integer.getInteger(nameString.substring(7));
if (Res_CHECKID(index)) {
ALOGW("Array resource index: %d is too large.",
index);
return 0;
}
if (outTypeSpecFlags != null) {
outTypeSpecFlags.set(ResTable_typeSpec.SPEC_PUBLIC);
}
return Res_MAKEARRAY(index);
}
return 0;
}
if (mError != NO_ERROR) {
return 0;
}
// Figure out the package and type we are looking in...
// TODO(BC): The following code block was a best effort attempt to directly transliterate
// C++ code which uses pointer artihmetic. Consider replacing with simpler logic
boolean fakePublic = false;
char[] name = nameString.toCharArray();
int packageEnd = -1;
int typeEnd = -1;
int nameEnd = name.length;
int pIndex = 0;
while (pIndex < nameEnd) {
char p = name[pIndex];
if (p == ':') packageEnd = pIndex;
else if (p == '/') typeEnd = pIndex;
pIndex++;
}
int nameIndex = 0;
if (name[nameIndex] == '@') {
nameIndex++;
if (name[nameIndex] == '*') {
fakePublic = true;
nameIndex++;
}
}
if (nameIndex >= nameEnd) {
return 0;
}
if (packageEnd != -1) {
packageName = nameString.substring(nameIndex, packageEnd);
nameIndex = packageEnd+1;
} else if (packageName == null) {
return 0;
}
if (typeEnd != -1) {
type = nameString.substring(nameIndex, typeEnd);
nameIndex = typeEnd+1;
} else if (type == null) {
return 0;
}
if (nameIndex >= nameEnd) {
return 0;
}
nameString = nameString.substring(nameIndex, nameEnd);
// nameLen = nameEnd-name;
// if (kDebugTableNoisy) {
// printf("Looking for identifier: type=%s, name=%s, package=%s\n",
// String8(type, typeLen).string(),
// String8(name, nameLen).string(),
// String8(package, packageLen).string());
// }
final String attr = "attr";
final String attrPrivate = "^attr-private";
for (PackageGroup group : mPackageGroups.values()) {
if (!Objects.equals(packageName.trim(), group.name.trim())) {
if (kDebugTableNoisy) {
System.out.println(String.format("Skipping package group: %s\n", group.name));
}
continue;
}
for (Package pkg : group.packages) {
String targetType = type;
do {
int ti = pkg.typeStrings.indexOfString(targetType);
if (ti < 0) {
continue;
}
ti += pkg.typeIdOffset;
int identifier = findEntry(group, ti, nameString, outTypeSpecFlags);
if (identifier != 0) {
if (fakePublic && outTypeSpecFlags != null) {
outTypeSpecFlags.set(outTypeSpecFlags.get() | ResTable_typeSpec.SPEC_PUBLIC);
}
return identifier;
}
} while (attr.compareTo(targetType) == 0
&& ((targetType = attrPrivate) != null)
);
}
break;
}
return 0;
}