public int identifierForName()

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;
  }