resources/src/main/java/org/robolectric/res/android/CppAssetManager2.java
ResolvedBag GetBag(int resid, List<Integer> child_resids) {
    // ATRACE_NAME("AssetManager::GetBag");

    ResolvedBag cached_iter = cached_bags_.get(resid);
    if (cached_iter != null) {
      return cached_iter;
    }

    final Ref<FindEntryResult> entryRef = new Ref<>(null);
    ApkAssetsCookie cookie =
        FindEntry(resid, (short) 0 /* density_override */, false /* stop_at_first_match */, entryRef);
    if (cookie.intValue() == kInvalidCookie) {
      return null;
    }

    FindEntryResult entry = entryRef.get();

    // Check that the size of the entry header is at least as big as
    // the desired ResTable_map_entry. Also verify that the entry
    // was intended to be a map.
    if (dtohs(entry.entry.size) < ResTable_map_entry.BASE_SIZEOF ||
        (dtohs(entry.entry.flags) & ResourceTypes.ResTable_entry.FLAG_COMPLEX) == 0) {
      // Not a bag, nothing to do.
      return null;
    }

    // final ResTable_map_entry map = reinterpret_cast<final ResTable_map_entry*>(entry.entry);
    // final ResTable_map map_entry =
    //     reinterpret_cast<final ResTable_map*>(reinterpret_cast<final byte*>(map) + map.size);
    // final ResTable_map map_entry_end = map_entry + dtohl(map.count);
    final ResTable_map_entry map = new ResTable_map_entry(entry.entry.myBuf(), entry.entry.myOffset());
    int curOffset = map.myOffset() + map.size;
    ResTable_map map_entry = null; // = new ResTable_map(map.myBuf(), curOffset);
    final int map_entry_end =
        curOffset + dtohl(map.count) * ResTable_map.SIZEOF;
    if (curOffset < map_entry_end) {
      map_entry = new ResTable_map(map.myBuf(), curOffset);
    }

    // Keep track of ids that have already been seen to prevent infinite loops caused by circular
    // dependencies between bags
    child_resids.add(resid);

    final Ref<Integer> parent_resid = new Ref<>(dtohl(map.parent.ident));
    if (parent_resid.get() == 0 || child_resids.contains(parent_resid.get())) {
      // There is no parent or that a circular dependency exist, meaning there is nothing to
      // inherit and we can do a simple copy of the entries in the map.
      final int entry_count = (map_entry_end - curOffset) / ResTable_map.SIZEOF;
      // util.unique_cptr<ResolvedBag> new_bag{reinterpret_cast<ResolvedBag*>(
      //     malloc(sizeof(ResolvedBag) + (entry_count * sizeof(ResolvedBag.Entry))))};
      ResolvedBag new_bag = new ResolvedBag();
      ResolvedBag.Entry[] new_entry = new_bag.entries = new Entry[entry_count];
      int i = 0;
      for (; curOffset < map_entry_end;
          map_entry = new ResTable_map(map_entry.myBuf(), curOffset)) {
        final Ref<Integer> new_key = new Ref<>(dtohl(map_entry.name.ident));
        if (!is_internal_resid(new_key.get())) {
          // Attributes, arrays, etc don't have a resource id as the name. They specify
          // other data, which would be wrong to change via a lookup.
          if (entry.dynamic_ref_table.lookupResourceId(new_key) != NO_ERROR) {
            System.err.println(String.format("Failed to resolve key 0x%08x in bag 0x%08x.", new_key.get(),
                resid));
            return null;
          }
        }
        Entry new_entry_ = new_entry[i] = new Entry();
        new_entry_.cookie = cookie;
        new_entry_.key = new_key.get();
        new_entry_.key_pool = null;
        new_entry_.type_pool = null;
        new_entry_.style = resid;
        new_entry_.value = map_entry.value.copy();
        final Ref<Res_value> valueRef = new Ref<>(new_entry_.value);
        int err = entry.dynamic_ref_table.lookupResourceValue(valueRef);
        new_entry_.value = valueRef.get();
        if (err != NO_ERROR) {
          System.err.println(String.format(
              "Failed to resolve value t=0x%02x d=0x%08x for key 0x%08x.", new_entry_.value.dataType,
              new_entry_.value.data, new_key.get()));
          return null;
        }
        // ++new_entry;
        ++i;

        final int size = dtohs(map_entry.value.size);
//      curOffset += size + sizeof(*map)-sizeof(map->value);
        curOffset += size + ResTable_map.SIZEOF-Res_value.SIZEOF;

      }
      new_bag.type_spec_flags = entry.type_flags;
      new_bag.entry_count = entry_count;
      ResolvedBag result = new_bag;
      cached_bags_.put(resid, new_bag);
      return result;
    }

    // In case the parent is a dynamic reference, resolve it.
    entry.dynamic_ref_table.lookupResourceId(parent_resid);

    // Get the parent and do a merge of the keys.
    final ResolvedBag parent_bag = GetBag(parent_resid.get(), child_resids);
    if (parent_bag == null) {
      // Failed to get the parent that should exist.
      System.err.println(String.format("Failed to find parent 0x%08x of bag 0x%08x.", parent_resid.get(),
          resid));
      return null;
    }

    // Create the max possible entries we can make. Once we construct the bag,
    // we will realloc to fit to size.
    final int max_count = parent_bag.entry_count + dtohl(map.count);
    // util::unique_cptr<ResolvedBag> new_bag{reinterpret_cast<ResolvedBag*>(
    //     malloc(sizeof(ResolvedBag) + (max_count * sizeof(ResolvedBag::Entry))))};
    ResolvedBag new_bag = new ResolvedBag();
    new_bag.entries = new Entry[max_count];
    final ResolvedBag.Entry[] new_entry = new_bag.entries;
    int newEntryIndex = 0;

  // const ResolvedBag::Entry* parent_entry = parent_bag->entries;
    int parentEntryIndex = 0;
    // final ResolvedBag.Entry parent_entry_end = parent_entry + parent_bag.entry_count;
    final int parentEntryCount = parent_bag.entry_count;

    // The keys are expected to be in sorted order. Merge the two bags.
    while (map_entry != null && map_entry.myOffset() != map_entry_end && parentEntryIndex != parentEntryCount) {
      final Ref<Integer> child_keyRef = new Ref<>(dtohl(map_entry.name.ident));
      if (!is_internal_resid(child_keyRef.get())) {
        if (entry.dynamic_ref_table.lookupResourceId(child_keyRef) != NO_ERROR) {
          System.err.println(String.format("Failed to resolve key 0x%08x in bag 0x%08x.", child_keyRef.get(),
              resid));
          return null;
        }
      }
      int child_key = child_keyRef.get();

      Entry parent_entry = parent_bag.entries[parentEntryIndex];
      if (parent_entry == null) {
        parent_entry = new Entry();
      }

      if (child_key <= parent_entry.key) {
        // Use the child key if it comes before the parent
        // or is equal to the parent (overrides).
        Entry new_entry_ = new_entry[newEntryIndex] = new Entry();
        new_entry_.cookie = cookie;
        new_entry_.key = child_key;
        new_entry_.key_pool = null;
        new_entry_.type_pool = null;
        new_entry_.value = map_entry.value.copy();
        new_entry_.style = resid;
        final Ref<Res_value> valueRef = new Ref<>(new_entry_.value);
        int err = entry.dynamic_ref_table.lookupResourceValue(valueRef);
        new_entry_.value = valueRef.get();
        if (err != NO_ERROR) {
          System.err.println(String.format(
              "Failed to resolve value t=0x%02x d=0x%08x for key 0x%08x.", new_entry_.value.dataType,
              new_entry_.value.data, child_key));
          return null;
        }

        // ++map_entry;
        map_entry = new ResTable_map(map_entry.myBuf(), map_entry.myOffset() + map_entry.value.size + ResTable_map.SIZEOF - Res_value.SIZEOF);
      } else {
        // Take the parent entry as-is.
        // memcpy(new_entry, parent_entry, sizeof(*new_entry));
        new_entry[newEntryIndex] = parent_entry.copy();
      }

      if (child_key >= parent_entry.key) {
        // Move to the next parent entry if we used it or it was overridden.
        // ++parent_entry;
        ++parentEntryIndex;
        // parent_entry = parent_bag.entries[parentEntryIndex];
      }
      // Increment to the next entry to fill.
      // ++new_entry;
      ++newEntryIndex;
    }

    // Finish the child entries if they exist.
    while (map_entry != null && map_entry.myOffset() != map_entry_end) {
      final Ref<Integer> new_key = new Ref<>(map_entry.name.ident);
      if (!is_internal_resid(new_key.get())) {
        if (entry.dynamic_ref_table.lookupResourceId(new_key) != NO_ERROR) {
          System.err.println(String.format("Failed to resolve key 0x%08x in bag 0x%08x.", new_key.get(),
              resid));
          return null;
        }
      }
      Entry new_entry_ = new_entry[newEntryIndex] = new Entry();
      new_entry_.cookie = cookie;
      new_entry_.key = new_key.get();
      new_entry_.key_pool = null;
      new_entry_.type_pool = null;
      new_entry_.value = map_entry.value.copy();
      new_entry_.style = resid;
      final Ref<Res_value> valueRef = new Ref<>(new_entry_.value);
      int err = entry.dynamic_ref_table.lookupResourceValue(valueRef);
      new_entry_.value = valueRef.get();
      if (err != NO_ERROR) {
        System.err.println(String.format(
            "Failed to resolve value t=0x%02x d=0x%08x for key 0x%08x.",
            new_entry_.value.dataType,
            new_entry_.value.data, new_key.get()));
        return null;
      }
      // ++map_entry;
      map_entry = new ResTable_map(map_entry.myBuf(), map_entry.myOffset() + map_entry.value.size + ResTable_map.SIZEOF - Res_value.SIZEOF);
      // ++new_entry;
      ++newEntryIndex;
    }

    // Finish the parent entries if they exist.
    while (parentEntryIndex != parent_bag.entry_count) {
      // Take the rest of the parent entries as-is.
      // final int num_entries_to_copy = parent_entry_end - parent_entry;
      // final int num_entries_to_copy = parent_bag.entry_count - parentEntryIndex;
      // memcpy(new_entry, parent_entry, num_entries_to_copy * sizeof(*new_entry));
      Entry parentEntry = parent_bag.entries[parentEntryIndex];
      new_entry[newEntryIndex] = parentEntry == null ? new Entry() : parentEntry.copy();
      // new_entry += num_entries_to_copy;
      ++newEntryIndex;
      ++parentEntryIndex;
    }

    // Resize the resulting array to fit.
    // final int actual_count = new_entry - new_bag.entries;
    final int actual_count = newEntryIndex;
    if (actual_count != max_count) {
      // new_bag.reset(reinterpret_cast<ResolvedBag*>(realloc(
      //     new_bag.release(), sizeof(ResolvedBag) + (actual_count * sizeof(ResolvedBag::Entry)))));
      Entry[] resizedEntries = new Entry[actual_count];
      System.arraycopy(new_bag.entries, 0, resizedEntries, 0, actual_count);
      new_bag.entries = resizedEntries;
    }

    // Combine flags from the parent and our own bag.
    new_bag.type_spec_flags = entry.type_flags | parent_bag.type_spec_flags;
    new_bag.entry_count = actual_count;
    ResolvedBag result2 = new_bag;
    // cached_bags_[resid] = std::move(new_bag);
    cached_bags_.put(resid, new_bag);
    return result2;
  }
ResolvedBag GetBag(int resid, List<Integer> child_resids) {
    // ATRACE_NAME("AssetManager::GetBag");

    ResolvedBag cached_iter = cached_bags_.get(resid);
    if (cached_iter != null) {
      return cached_iter;
    }

    final Ref<FindEntryResult> entryRef = new Ref<>(null);
    ApkAssetsCookie cookie =
        FindEntry(resid, (short) 0 /* density_override */, false /* stop_at_first_match */, entryRef);
    if (cookie.intValue() == kInvalidCookie) {
      return null;
    }

    FindEntryResult entry = entryRef.get();

    // Check that the size of the entry header is at least as big as
    // the desired ResTable_map_entry. Also verify that the entry
    // was intended to be a map.
    if (dtohs(entry.entry.size) < ResTable_map_entry.BASE_SIZEOF ||
        (dtohs(entry.entry.flags) & ResourceTypes.ResTable_entry.FLAG_COMPLEX) == 0) {
      // Not a bag, nothing to do.
      return null;
    }

    // final ResTable_map_entry map = reinterpret_cast<final ResTable_map_entry*>(entry.entry);
    // final ResTable_map map_entry =
    //     reinterpret_cast<final ResTable_map*>(reinterpret_cast<final byte*>(map) + map.size);
    // final ResTable_map map_entry_end = map_entry + dtohl(map.count);
    final ResTable_map_entry map = new ResTable_map_entry(entry.entry.myBuf(), entry.entry.myOffset());
    int curOffset = map.myOffset() + map.size;
    ResTable_map map_entry = null; // = new ResTable_map(map.myBuf(), curOffset);
    final int map_entry_end =
        curOffset + dtohl(map.count) * ResTable_map.SIZEOF;
    if (curOffset < map_entry_end) {
      map_entry = new ResTable_map(map.myBuf(), curOffset);
    }

    // Keep track of ids that have already been seen to prevent infinite loops caused by circular
    // dependencies between bags
    child_resids.add(resid);

    final Ref<Integer> parent_resid = new Ref<>(dtohl(map.parent.ident));
    if (parent_resid.get() == 0 || child_resids.contains(parent_resid.get())) {
      // There is no parent or that a circular dependency exist, meaning there is nothing to
      // inherit and we can do a simple copy of the entries in the map.
      final int entry_count = (map_entry_end - curOffset) / ResTable_map.SIZEOF;
      // util.unique_cptr<ResolvedBag> new_bag{reinterpret_cast<ResolvedBag*>(
      //     malloc(sizeof(ResolvedBag) + (entry_count * sizeof(ResolvedBag.Entry))))};
      ResolvedBag new_bag = new ResolvedBag();
      ResolvedBag.Entry[] new_entry = new_bag.entries = new Entry[entry_count];
      int i = 0;
      for (; curOffset < map_entry_end;
          map_entry = new ResTable_map(map_entry.myBuf(), curOffset)) {
        final Ref<Integer> new_key = new Ref<>(dtohl(map_entry.name.ident));
        if (!is_internal_resid(new_key.get())) {
          // Attributes, arrays, etc don't have a resource id as the name. They specify
          // other data, which would be wrong to change via a lookup.
          if (entry.dynamic_ref_table.lookupResourceId(new_key) != NO_ERROR) {
            System.err.println(String.format("Failed to resolve key 0x%08x in bag 0x%08x.", new_key.get(),
                resid));
            return null;
          }
        }
        Entry new_entry_ = new_entry[i] = new Entry();
        new_entry_.cookie = cookie;
        new_entry_.key = new_key.get();
        new_entry_.key_pool = null;
        new_entry_.type_pool = null;
        new_entry_.style = resid;
        new_entry_.value = map_entry.value.copy();
        final Ref<Res_value> valueRef = new Ref<>(new_entry_.value);
        int err = entry.dynamic_ref_table.lookupResourceValue(valueRef);
        new_entry_.value = valueRef.get();
        if (err != NO_ERROR) {
          System.err.println(String.format(
              "Failed to resolve value t=0x%02x d=0x%08x for key 0x%08x.", new_entry_.value.dataType,
              new_entry_.value.data, new_key.get()));
          return null;
        }
        // ++new_entry;
        ++i;

        final int size = dtohs(map_entry.value.size);
//      curOffset += size + sizeof(*map)-sizeof(map->value);
        curOffset += size + ResTable_map.SIZEOF-Res_value.SIZEOF;

      }
      new_bag.type_spec_flags = entry.type_flags;
      new_bag.entry_count = entry_count;
      ResolvedBag result = new_bag;
      cached_bags_.put(resid, new_bag);
      return result;
    }

    // In case the parent is a dynamic reference, resolve it.
    entry.dynamic_ref_table.lookupResourceId(parent_resid);

    // Get the parent and do a merge of the keys.
    final ResolvedBag parent_bag = GetBag(parent_resid.get(), child_resids);
    if (parent_bag == null) {
      // Failed to get the parent that should exist.
      System.err.println(String.format("Failed to find parent 0x%08x of bag 0x%08x.", parent_resid.get(),
          resid));
      return null;
    }

    // Create the max possible entries we can make. Once we construct the bag,
    // we will realloc to fit to size.
    final int max_count = parent_bag.entry_count + dtohl(map.count);
    // util::unique_cptr<ResolvedBag> new_bag{reinterpret_cast<ResolvedBag*>(
    //     malloc(sizeof(ResolvedBag) + (max_count * sizeof(ResolvedBag::Entry))))};
    ResolvedBag new_bag = new ResolvedBag();
    new_bag.entries = new Entry[max_count];
    final ResolvedBag.Entry[] new_entry = new_bag.entries;
    int newEntryIndex = 0;

  // const ResolvedBag::Entry* parent_entry = parent_bag->entries;
    int parentEntryIndex = 0;
    // final ResolvedBag.Entry parent_entry_end = parent_entry + parent_bag.entry_count;
    final int parentEntryCount = parent_bag.entry_count;

    // The keys are expected to be in sorted order. Merge the two bags.
    while (map_entry != null && map_entry.myOffset() != map_entry_end && parentEntryIndex != parentEntryCount) {
      final Ref<Integer> child_keyRef = new Ref<>(dtohl(map_entry.name.ident));
      if (!is_internal_resid(child_keyRef.get())) {
        if (entry.dynamic_ref_table.lookupResourceId(child_keyRef) != NO_ERROR) {
          System.err.println(String.format("Failed to resolve key 0x%08x in bag 0x%08x.", child_keyRef.get(),
              resid));
          return null;
        }
      }
      int child_key = child_keyRef.get();

      Entry parent_entry = parent_bag.entries[parentEntryIndex];
      if (parent_entry == null) {
        parent_entry = new Entry();
      }

      if (child_key <= parent_entry.key) {
        // Use the child key if it comes before the parent
        // or is equal to the parent (overrides).
        Entry new_entry_ = new_entry[newEntryIndex] = new Entry();
        new_entry_.cookie = cookie;
        new_entry_.key = child_key;
        new_entry_.key_pool = null;
        new_entry_.type_pool = null;
        new_entry_.value = map_entry.value.copy();
        new_entry_.style = resid;
        final Ref<Res_value> valueRef = new Ref<>(new_entry_.value);
        int err = entry.dynamic_ref_table.lookupResourceValue(valueRef);
        new_entry_.value = valueRef.get();
        if (err != NO_ERROR) {
          System.err.println(String.format(
              "Failed to resolve value t=0x%02x d=0x%08x for key 0x%08x.", new_entry_.value.dataType,
              new_entry_.value.data, child_key));
          return null;
        }

        // ++map_entry;
        map_entry = new ResTable_map(map_entry.myBuf(), map_entry.myOffset() + map_entry.value.size + ResTable_map.SIZEOF - Res_value.SIZEOF);
      } else {
        // Take the parent entry as-is.
        // memcpy(new_entry, parent_entry, sizeof(*new_entry));
        new_entry[newEntryIndex] = parent_entry.copy();
      }

      if (child_key >= parent_entry.key) {
        // Move to the next parent entry if we used it or it was overridden.
        // ++parent_entry;
        ++parentEntryIndex;
        // parent_entry = parent_bag.entries[parentEntryIndex];
      }
      // Increment to the next entry to fill.
      // ++new_entry;
      ++newEntryIndex;
    }

    // Finish the child entries if they exist.
    while (map_entry != null && map_entry.myOffset() != map_entry_end) {
      final Ref<Integer> new_key = new Ref<>(map_entry.name.ident);
      if (!is_internal_resid(new_key.get())) {
        if (entry.dynamic_ref_table.lookupResourceId(new_key) != NO_ERROR) {
          System.err.println(String.format("Failed to resolve key 0x%08x in bag 0x%08x.", new_key.get(),
              resid));
          return null;
        }
      }
      Entry new_entry_ = new_entry[newEntryIndex] = new Entry();
      new_entry_.cookie = cookie;
      new_entry_.key = new_key.get();
      new_entry_.key_pool = null;
      new_entry_.type_pool = null;
      new_entry_.value = map_entry.value.copy();
      new_entry_.style = resid;
      final Ref<Res_value> valueRef = new Ref<>(new_entry_.value);
      int err = entry.dynamic_ref_table.lookupResourceValue(valueRef);
      new_entry_.value = valueRef.get();
      if (err != NO_ERROR) {
        System.err.println(String.format(
            "Failed to resolve value t=0x%02x d=0x%08x for key 0x%08x.",
            new_entry_.value.dataType,
            new_entry_.value.data, new_key.get()));
        return null;
      }
      // ++map_entry;
      map_entry = new ResTable_map(map_entry.myBuf(), map_entry.myOffset() + map_entry.value.size + ResTable_map.SIZEOF - Res_value.SIZEOF);
      // ++new_entry;
      ++newEntryIndex;
    }

    // Finish the parent entries if they exist.
    while (parentEntryIndex != parent_bag.entry_count) {
      // Take the rest of the parent entries as-is.
      // final int num_entries_to_copy = parent_entry_end - parent_entry;
      // final int num_entries_to_copy = parent_bag.entry_count - parentEntryIndex;
      // memcpy(new_entry, parent_entry, num_entries_to_copy * sizeof(*new_entry));
      Entry parentEntry = parent_bag.entries[parentEntryIndex];
      new_entry[newEntryIndex] = parentEntry == null ? new Entry() : parentEntry.copy();
      // new_entry += num_entries_to_copy;
      ++newEntryIndex;
      ++parentEntryIndex;
    }

    // Resize the resulting array to fit.
    // final int actual_count = new_entry - new_bag.entries;
    final int actual_count = newEntryIndex;
    if (actual_count != max_count) {
      // new_bag.reset(reinterpret_cast<ResolvedBag*>(realloc(
      //     new_bag.release(), sizeof(ResolvedBag) + (actual_count * sizeof(ResolvedBag::Entry)))));
      Entry[] resizedEntries = new Entry[actual_count];
      System.arraycopy(new_bag.entries, 0, resizedEntries, 0, actual_count);
      new_bag.entries = resizedEntries;
    }

    // Combine flags from the parent and our own bag.
    new_bag.type_spec_flags = entry.type_flags | parent_bag.type_spec_flags;
    new_bag.entry_count = actual_count;
    ResolvedBag result2 = new_bag;
    // cached_bags_[resid] = std::move(new_bag);
    cached_bags_.put(resid, new_bag);
    return result2;
  }
ResolvedBag GetBag ( int resid , List < Integer > child_resids ) { // ATRACE_NAME("AssetManager::GetBag"); ResolvedBag cached_iter = cached_bags_ . get ( resid ) ; if ( cached_iter != null ) { return cached_iter ; } final Ref < FindEntryResult > entryRef = new Ref <> ( null ) ; ApkAssetsCookie cookie = FindEntry ( resid , ( short ) 0 /* density_override */ , false /* stop_at_first_match */ , entryRef ) ; if ( cookie . intValue ( ) == kInvalidCookie ) { return null ; } FindEntryResult entry = entryRef . get ( ) ; // Check that the size of the entry header is at least as big as // the desired ResTable_map_entry. Also verify that the entry // was intended to be a map. if ( dtohs ( entry . entry . size ) < ResTable_map_entry . BASE_SIZEOF || ( dtohs ( entry . entry . flags ) & ResourceTypes . ResTable_entry . FLAG_COMPLEX ) == 0 ) { // Not a bag, nothing to do. return null ; } // final ResTable_map_entry map = reinterpret_cast<final ResTable_map_entry*>(entry.entry); // final ResTable_map map_entry = //     reinterpret_cast<final ResTable_map*>(reinterpret_cast<final byte*>(map) + map.size); // final ResTable_map map_entry_end = map_entry + dtohl(map.count); final ResTable_map_entry map = new ResTable_map_entry ( entry . entry . myBuf ( ) , entry . entry . myOffset ( ) ) ; int curOffset = map . myOffset ( ) + map . size ; ResTable_map map_entry = null ; // = new ResTable_map(map.myBuf(), curOffset); final int map_entry_end = curOffset + dtohl ( map . count ) * ResTable_map . SIZEOF ; if ( curOffset < map_entry_end ) { map_entry = new ResTable_map ( map . myBuf ( ) , curOffset ) ; } // Keep track of ids that have already been seen to prevent infinite loops caused by circular // dependencies between bags child_resids . add ( resid ) ; final Ref < Integer > parent_resid = new Ref <> ( dtohl ( map . parent . ident ) ) ; if ( parent_resid . get ( ) == 0 || child_resids . contains ( parent_resid . get ( ) ) ) { // There is no parent or that a circular dependency exist, meaning there is nothing to // inherit and we can do a simple copy of the entries in the map. final int entry_count = ( map_entry_end - curOffset ) / ResTable_map . SIZEOF ; // util.unique_cptr<ResolvedBag> new_bag{reinterpret_cast<ResolvedBag*>( //     malloc(sizeof(ResolvedBag) + (entry_count * sizeof(ResolvedBag.Entry))))}; ResolvedBag new_bag = new ResolvedBag ( ) ; ResolvedBag . Entry [ ] new_entry = new_bag . entries = new Entry [ entry_count ] ; int i = 0 ; for ( ; curOffset < map_entry_end ; map_entry = new ResTable_map ( map_entry . myBuf ( ) , curOffset ) ) { final Ref < Integer > new_key = new Ref <> ( dtohl ( map_entry . name . ident ) ) ; if ( ! is_internal_resid ( new_key . get ( ) ) ) { // Attributes, arrays, etc don't have a resource id as the name. They specify // other data, which would be wrong to change via a lookup. if ( entry . dynamic_ref_table . lookupResourceId ( new_key ) != NO_ERROR ) { System . err . println ( String . format ( "Failed to resolve key 0x%08x in bag 0x%08x." , new_key . get ( ) , resid ) ) ; return null ; } } Entry new_entry_ = new_entry [ i ] = new Entry ( ) ; new_entry_ . cookie = cookie ; new_entry_ . key = new_key . get ( ) ; new_entry_ . key_pool = null ; new_entry_ . type_pool = null ; new_entry_ . style = resid ; new_entry_ . value = map_entry . value . copy ( ) ; final Ref < Res_value > valueRef = new Ref <> ( new_entry_ . value ) ; int err = entry . dynamic_ref_table . lookupResourceValue ( valueRef ) ; new_entry_ . value = valueRef . get ( ) ; if ( err != NO_ERROR ) { System . err . println ( String . format ( "Failed to resolve value t=0x%02x d=0x%08x for key 0x%08x." , new_entry_ . value . dataType , new_entry_ . value . data , new_key . get ( ) ) ) ; return null ; } // ++new_entry; ++ i ; final int size = dtohs ( map_entry . value . size ) ; //      curOffset += size + sizeof(*map)-sizeof(map->value); curOffset += size + ResTable_map . SIZEOF - Res_value . SIZEOF ; } new_bag . type_spec_flags = entry . type_flags ; new_bag . entry_count = entry_count ; ResolvedBag result = new_bag ; cached_bags_ . put ( resid , new_bag ) ; return result ; } // In case the parent is a dynamic reference, resolve it. entry . dynamic_ref_table . lookupResourceId ( parent_resid ) ; // Get the parent and do a merge of the keys. final ResolvedBag parent_bag = GetBag ( parent_resid . get ( ) , child_resids ) ; if ( parent_bag == null ) { // Failed to get the parent that should exist. System . err . println ( String . format ( "Failed to find parent 0x%08x of bag 0x%08x." , parent_resid . get ( ) , resid ) ) ; return null ; } // Create the max possible entries we can make. Once we construct the bag, // we will realloc to fit to size. final int max_count = parent_bag . entry_count + dtohl ( map . count ) ; // util::unique_cptr<ResolvedBag> new_bag{reinterpret_cast<ResolvedBag*>( //     malloc(sizeof(ResolvedBag) + (max_count * sizeof(ResolvedBag::Entry))))}; ResolvedBag new_bag = new ResolvedBag ( ) ; new_bag . entries = new Entry [ max_count ] ; final ResolvedBag . Entry [ ] new_entry = new_bag . entries ; int newEntryIndex = 0 ; // const ResolvedBag::Entry* parent_entry = parent_bag->entries; int parentEntryIndex = 0 ; // final ResolvedBag.Entry parent_entry_end = parent_entry + parent_bag.entry_count; final int parentEntryCount = parent_bag . entry_count ; // The keys are expected to be in sorted order. Merge the two bags. while ( map_entry != null && map_entry . myOffset ( ) != map_entry_end && parentEntryIndex != parentEntryCount ) { final Ref < Integer > child_keyRef = new Ref <> ( dtohl ( map_entry . name . ident ) ) ; if ( ! is_internal_resid ( child_keyRef . get ( ) ) ) { if ( entry . dynamic_ref_table . lookupResourceId ( child_keyRef ) != NO_ERROR ) { System . err . println ( String . format ( "Failed to resolve key 0x%08x in bag 0x%08x." , child_keyRef . get ( ) , resid ) ) ; return null ; } } int child_key = child_keyRef . get ( ) ; Entry parent_entry = parent_bag . entries [ parentEntryIndex ] ; if ( parent_entry == null ) { parent_entry = new Entry ( ) ; } if ( child_key <= parent_entry . key ) { // Use the child key if it comes before the parent // or is equal to the parent (overrides). Entry new_entry_ = new_entry [ newEntryIndex ] = new Entry ( ) ; new_entry_ . cookie = cookie ; new_entry_ . key = child_key ; new_entry_ . key_pool = null ; new_entry_ . type_pool = null ; new_entry_ . value = map_entry . value . copy ( ) ; new_entry_ . style = resid ; final Ref < Res_value > valueRef = new Ref <> ( new_entry_ . value ) ; int err = entry . dynamic_ref_table . lookupResourceValue ( valueRef ) ; new_entry_ . value = valueRef . get ( ) ; if ( err != NO_ERROR ) { System . err . println ( String . format ( "Failed to resolve value t=0x%02x d=0x%08x for key 0x%08x." , new_entry_ . value . dataType , new_entry_ . value . data , child_key ) ) ; return null ; } // ++map_entry; map_entry = new ResTable_map ( map_entry . myBuf ( ) , map_entry . myOffset ( ) + map_entry . value . size + ResTable_map . SIZEOF - Res_value . SIZEOF ) ; } else { // Take the parent entry as-is. // memcpy(new_entry, parent_entry, sizeof(*new_entry)); new_entry [ newEntryIndex ] = parent_entry . copy ( ) ; } if ( child_key >= parent_entry . key ) { // Move to the next parent entry if we used it or it was overridden. // ++parent_entry; ++ parentEntryIndex ; // parent_entry = parent_bag.entries[parentEntryIndex]; } // Increment to the next entry to fill. // ++new_entry; ++ newEntryIndex ; } // Finish the child entries if they exist. while ( map_entry != null && map_entry . myOffset ( ) != map_entry_end ) { final Ref < Integer > new_key = new Ref <> ( map_entry . name . ident ) ; if ( ! is_internal_resid ( new_key . get ( ) ) ) { if ( entry . dynamic_ref_table . lookupResourceId ( new_key ) != NO_ERROR ) { System . err . println ( String . format ( "Failed to resolve key 0x%08x in bag 0x%08x." , new_key . get ( ) , resid ) ) ; return null ; } } Entry new_entry_ = new_entry [ newEntryIndex ] = new Entry ( ) ; new_entry_ . cookie = cookie ; new_entry_ . key = new_key . get ( ) ; new_entry_ . key_pool = null ; new_entry_ . type_pool = null ; new_entry_ . value = map_entry . value . copy ( ) ; new_entry_ . style = resid ; final Ref < Res_value > valueRef = new Ref <> ( new_entry_ . value ) ; int err = entry . dynamic_ref_table . lookupResourceValue ( valueRef ) ; new_entry_ . value = valueRef . get ( ) ; if ( err != NO_ERROR ) { System . err . println ( String . format ( "Failed to resolve value t=0x%02x d=0x%08x for key 0x%08x." , new_entry_ . value . dataType , new_entry_ . value . data , new_key . get ( ) ) ) ; return null ; } // ++map_entry; map_entry = new ResTable_map ( map_entry . myBuf ( ) , map_entry . myOffset ( ) + map_entry . value . size + ResTable_map . SIZEOF - Res_value . SIZEOF ) ; // ++new_entry; ++ newEntryIndex ; } // Finish the parent entries if they exist. while ( parentEntryIndex != parent_bag . entry_count ) { // Take the rest of the parent entries as-is. // final int num_entries_to_copy = parent_entry_end - parent_entry; // final int num_entries_to_copy = parent_bag.entry_count - parentEntryIndex; // memcpy(new_entry, parent_entry, num_entries_to_copy * sizeof(*new_entry)); Entry parentEntry = parent_bag . entries [ parentEntryIndex ] ; new_entry [ newEntryIndex ] = parentEntry == null ? new Entry ( ) : parentEntry . copy ( ) ; // new_entry += num_entries_to_copy; ++ newEntryIndex ; ++ parentEntryIndex ; } // Resize the resulting array to fit. // final int actual_count = new_entry - new_bag.entries; final int actual_count = newEntryIndex ; if ( actual_count != max_count ) { // new_bag.reset(reinterpret_cast<ResolvedBag*>(realloc( //     new_bag.release(), sizeof(ResolvedBag) + (actual_count * sizeof(ResolvedBag::Entry))))); Entry [ ] resizedEntries = new Entry [ actual_count ] ; System . arraycopy ( new_bag . entries , 0 , resizedEntries , 0 , actual_count ) ; new_bag . entries = resizedEntries ; } // Combine flags from the parent and our own bag. new_bag . type_spec_flags = entry . type_flags | parent_bag . type_spec_flags ; new_bag . entry_count = actual_count ; ResolvedBag result2 = new_bag ; // cached_bags_[resid] = std::move(new_bag); cached_bags_ . put ( resid , new_bag ) ; return result2 ; }
}
}