void ModificationMap::applyModifications(UpdatableByteContainer &ubc) {
  if(isEmpty()) {
    return;
  }

  Iterator<Entry<__int64, BytePair> > it = entrySet().getIterator();
  Entry<__int64, BytePair> &e = it.next();

  __int64 seqStartAddr = e.getKey();
  __int64 lastAddr     = seqStartAddr;
  ByteArray byteSequence;
  byteSequence.append(e.getValue().getTo());
  while(it.hasNext()) {
    Entry<__int64, BytePair> &e1 = it.next();
    const __int64 addr = e1.getKey();
    if(addr != lastAddr+1) {
      ubc.putBytes(seqStartAddr, byteSequence);
      byteSequence.clear();
      seqStartAddr = addr;
    }
    byteSequence.append(e1.getValue().getTo());
    lastAddr = addr;
  }
  ubc.putBytes(seqStartAddr, byteSequence); // byteSequence is NOT empty
}
void ModificationMap::applyModifications(unsigned __int64 offset, ByteArray &content) {
  const AddrRange modifiedRange = getAddrRange();
  const __int64 lastOffset = offset + content.size()-1;
  const AddrRange dataRange(offset, lastOffset);
  if(modifiedRange.overlap(dataRange)) {
    for(Iterator<Entry<__int64, BytePair> > it = entrySet().getIterator(); it.hasNext();) {
      const Entry<__int64, BytePair> &e = it.next();
      const __int64 &key = e.getKey();
      if(key >= (__int64)offset) {
        if(key <= lastOffset) {
          content[(UINT)(key - (__int64)offset)] = e.getValue().getTo();
        } else {
          break; // we're done
        }
      }
    }
  }
}
void getMap(jobject jobj, const std::function<void(jobject, jobject)> &cb) {
  const Context::Handle ctx = Context::getContext();
  LocalRef<jclass> clazz(ctx->env()->GetObjectClass(jobj));
  const jmethodID entrySetId =
      ctx->env()->GetMethodID(clazz.get(), "entrySet", "()Ljava/util/Set;");
  LocalRef<jobject> entrySet(ctx->env()->CallObjectMethod(jobj, entrySetId));
  LocalRef<jclass> mapEntryClass(ctx->env()->FindClass("java/util/Map$Entry"));
  const jmethodID getKeyId = ctx->env()->GetMethodID(
      mapEntryClass.get(), "getKey", "()Ljava/lang/Object;");
  const jmethodID getValueId = ctx->env()->GetMethodID(
      mapEntryClass.get(), "getValue", "()Ljava/lang/Object;");
  ctx->throwIfOccured();
  getIterable(entrySet.get(), [&ctx, &cb, getKeyId, getValueId](jobject jobj) {
    LocalRef<jobject> jkey(ctx->env()->CallObjectMethod(jobj, getKeyId));
    LocalRef<jobject> jvalue(ctx->env()->CallObjectMethod(jobj, getValueId));
    cb(jkey.get(), jvalue.get());
  });
}