1 package org.robolectric.res.android; 2 3 // transliterated from 4 // https://android.googlesource.com/platform/frameworks/base/+/android-9.0.0_r12/libs/androidfw/include/androidfw/ResourceUtils.h 5 // and https://android.googlesource.com/platform/frameworks/base/+/android-9.0.0_r12/libs/androidfw/ResourceUtils.cpp 6 class ResourceUtils { 7 // Extracts the package, type, and name from a string of the format: [[package:]type/]name 8 // Validation must be performed on each extracted piece. 9 // Returns false if there was a syntax error. 10 // boolean ExtractResourceName(String& str, String* out_package, String* out_type, 11 // String* out_entry); 12 fix_package_id(int resid, int package_id)13 static int fix_package_id(int resid, int package_id) { 14 return (resid & 0x00ffffff) | (package_id << 24); 15 } 16 get_package_id(int resid)17 static int get_package_id(int resid) { 18 // return static_cast<int>((resid >> 24) & 0x000000ff); 19 return resid >>> 24; 20 } 21 22 // The type ID is 1-based, so if the returned value is 0 it is invalid. get_type_id(int resid)23 static int get_type_id(int resid) { 24 // return static_cast<int>((resid >> 16) & 0x000000ff); 25 return (resid & 0x00FF0000) >>> 16; 26 } 27 get_entry_id(int resid)28 static int get_entry_id(int resid) { 29 // return static_cast<uint16_t>(resid & 0x0000ffff); 30 return (short) (resid & 0x0000FFFF); 31 } 32 is_internal_resid(int resid)33 static boolean is_internal_resid(int resid) { 34 return (resid & 0xffff0000) != 0 && (resid & 0x00ff0000) == 0; 35 } 36 is_valid_resid(int resid)37 static boolean is_valid_resid(int resid) { 38 return (resid & 0x00ff0000) != 0 && (resid & 0xff000000) != 0; 39 } 40 make_resid(byte package_id, byte type_id, short entry_id)41 static int make_resid(byte package_id, byte type_id, short entry_id) { 42 // return (static_cast<int>(package_id) << 24) | (static_cast<int>(type_id) << 16) | 43 // entry_id; 44 return package_id << 24 | type_id << 16 | entry_id; 45 } 46 47 // bool ExtractResourceName(const StringPiece& str, StringPiece* out_package, StringPiece* out_type, 48 // StringPiece* out_entry) { 49 // *out_package = ""; 50 // *out_type = ""; 51 // bool has_package_separator = false; 52 // bool has_type_separator = false; 53 // const char* start = str.data(); 54 // const char* end = start + str.size(); 55 // const char* current = start; 56 // while (current != end) { 57 // if (out_type->size() == 0 && *current == '/') { 58 // has_type_separator = true; 59 // out_type->assign(start, current - start); 60 // start = current + 1; 61 // } else if (out_package->size() == 0 && *current == ':') { 62 // has_package_separator = true; 63 // out_package->assign(start, current - start); 64 // start = current + 1; 65 // } 66 // current++; 67 // } 68 // out_entry->assign(start, end - start); 69 // 70 // return !(has_package_separator && out_package->empty()) && 71 // !(has_type_separator && out_type->empty()); 72 // } 73 ExtractResourceName(String str, Ref<String> out_package, Ref<String> out_type, final Ref<String> out_entry)74 static boolean ExtractResourceName(String str, Ref<String> out_package, Ref<String> out_type, 75 final Ref<String> out_entry) { 76 out_package.set(""); 77 out_type.set(""); 78 boolean has_package_separator = false; 79 boolean has_type_separator = false; 80 int start = 0; 81 int end = start + str.length(); 82 int current = start; 83 while (current != end) { 84 if (out_type.get().length() == 0 && str.charAt(current) == '/') { 85 has_type_separator = true; 86 out_type.set(str.substring(start, current)); 87 start = current + 1; 88 } else if (out_package.get().length() == 0 && str.charAt(current) == ':') { 89 has_package_separator = true; 90 out_package.set(str.substring(start, current)); 91 start = current + 1; 92 } 93 current++; 94 } 95 out_entry.set(str.substring(start, end)); 96 97 return !(has_package_separator && out_package.get().isEmpty()) && 98 !(has_type_separator && out_type.get().isEmpty()); 99 } 100 101 } 102