int addInternal()

in resources/src/main/java/org/robolectric/res/android/ResTable.java [221:359]


  int addInternal(byte[] data, int dataSize, final Object idmapData, int idmapDataSize,
      boolean appAsLib, final int cookie, boolean copyData, boolean isSystemAsset)
  {
    if (!isTruthy(data)) {
      return NO_ERROR;
    }

    if (dataSize < ResTable_header.SIZEOF) {
      ALOGE("Invalid data. Size(%d) is smaller than a ResTable_header(%d).",
          (int) dataSize, (int) ResTable_header.SIZEOF);
      return UNKNOWN_ERROR;
    }

    Header header = new Header(this);
    header.index = mHeaders.size();
    header.cookie = cookie;
    if (idmapData != NULL) {
      header.resourceIDMap = new int[idmapDataSize / 4];
      if (header.resourceIDMap == NULL) {
//        delete header;
        return (mError = NO_MEMORY);
      }
//      memcpy(header.resourceIDMap, idmapData, idmapDataSize);
//      header.resourceIDMapSize = idmapDataSize;
    }
    mHeaders.add(header);

    final boolean notDeviceEndian = htods((short) 0xf0) != 0xf0;

    if (kDebugLoadTableNoisy) {
      ALOGV("Adding resources to ResTable: data=%s, size=0x%x, cookie=%d, copy=%d " +
          "idmap=%s\n", data, dataSize, cookie, copyData, idmapData);
    }

    if (copyData || notDeviceEndian) {
      header.ownedData = data; // malloc(dataSize);
      if (header.ownedData == NULL) {
        return (mError=NO_MEMORY);
      }
//      memcpy(header.ownedData, data, dataSize);
      data = header.ownedData;
    }

    ByteBuffer buf = ByteBuffer.wrap(data).order(ByteOrder.LITTLE_ENDIAN);
//    header->header = (const ResTable_header*)data;
    header.header = new ResTable_header(buf, 0);
    header.size = dtohl(header.header.header.size);
    if (kDebugLoadTableSuperNoisy) {
      ALOGI("Got size 0x%x, again size 0x%x, raw size 0x%x\n", header.size,
          dtohl(header.header.header.size), header.header.header.size);
    }
    if (kDebugLoadTableNoisy) {
      ALOGV("Loading ResTable @%s:\n", header.header);
    }
    if (dtohs(header.header.header.headerSize) > header.size
        || header.size > dataSize) {
      ALOGW("Bad resource table: header size 0x%x or total size 0x%x is larger than data size 0x%x\n",
          (int)dtohs(header.header.header.headerSize),
          (int)header.size, (int)dataSize);
      return (mError=BAD_TYPE);
    }
    if (((dtohs(header.header.header.headerSize)|header.size)&0x3) != 0) {
      ALOGW("Bad resource table: header size 0x%x or total size 0x%x is not on an integer boundary\n",
          (int)dtohs(header.header.header.headerSize),
          (int)header.size);
      return (mError=BAD_TYPE);
    }
//    header->dataEnd = ((const uint8_t*)header->header) + header->size;
    header.dataEnd = header.size;

    // Iterate through all chunks.
    int curPackage = 0;

//    const ResChunk_header* chunk =
//      (const ResChunk_header*)(((const uint8_t*)header->header)
//    + dtohs(header->header->header.headerSize));
    ResChunk_header chunk =
      new ResChunk_header(buf, dtohs(header.header.header.headerSize));
    while (chunk != null && (chunk.myOffset()) <= (header.dataEnd -ResChunk_header.SIZEOF) &&
      (chunk.myOffset()) <= (header.dataEnd -dtohl(chunk.size))) {
    int err = validate_chunk(chunk, ResChunk_header.SIZEOF, header.dataEnd, "ResTable");
    if (err != NO_ERROR) {
      return (mError=err);
    }
    if (kDebugTableNoisy) {
      ALOGV("Chunk: type=0x%x, headerSize=0x%x, size=0x%x, pos=%s\n",
          dtohs(chunk.type), dtohs(chunk.headerSize), dtohl(chunk.size),
          (Object)((chunk.myOffset()) - (header.header.myOffset())));
    }
    final int csize = dtohl(chunk.size);
    final int ctype = dtohs(chunk.type);
    if (ctype == RES_STRING_POOL_TYPE) {
      if (header.values.getError() != NO_ERROR) {
        // Only use the first string chunk; ignore any others that
        // may appear.
        err = header.values.setTo(chunk.myBuf(), chunk.myOffset(), csize, false);
        if (err != NO_ERROR) {
          return (mError=err);
        }
      } else {
        ALOGW("Multiple string chunks found in resource table.");
      }
    } else if (ctype == RES_TABLE_PACKAGE_TYPE) {
      if (curPackage >= dtohl(header.header.packageCount)) {
        ALOGW("More package chunks were found than the %d declared in the header.",
            dtohl(header.header.packageCount));
        return (mError=BAD_TYPE);
      }

      if (parsePackage(
          new ResTable_package(chunk.myBuf(), chunk.myOffset()), header, appAsLib, isSystemAsset) != NO_ERROR) {
        return mError;
      }
      curPackage++;
    } else {
      ALOGW("Unknown chunk type 0x%x in table at 0x%x.\n",
          ctype,
          (chunk.myOffset()) - (header.header.myOffset()));
    }
    chunk = chunk.myOffset() + csize < header.dataEnd
        ? new ResChunk_header(chunk.myBuf(), chunk.myOffset() + csize)
        : null;
  }

    if (curPackage < dtohl(header.header.packageCount)) {
      ALOGW("Fewer package chunks (%d) were found than the %d declared in the header.",
          (int)curPackage, dtohl(header.header.packageCount));
      return (mError=BAD_TYPE);
    }
    mError = header.values.getError();
    if (mError != NO_ERROR) {
      ALOGW("No string values found in resource table!");
    }

    if (kDebugTableNoisy) {
      ALOGV("Returning from add with mError=%d\n", mError);
    }
    return mError;
  }