// File: /workspace/github_c_makefile_star2_O2/ukontainer[P]sqlite-bench/sqlite3.c
// Function: blobReadWrite
static int blobReadWrite(
  sqlite3_blob *pBlob, 
  void *z, 
  int n, 
  int iOffset, 
  int (*xCall)(BtCursor*, u32, u32, void*)
){
  int rc;
  Incrblob *p = (Incrblob *)pBlob;
  Vdbe *v;
  sqlite3 *db;

  if( p==0 ) return SQLITE_MISUSE_BKPT;
  db = p->db;
  sqlite3_mutex_enter(db->mutex);
  v = (Vdbe*)p->pStmt;

  if( n<0 || iOffset<0 || ((sqlite3_int64)iOffset+n)>p->nByte ){
    /* Request is out of range. Return a transient error. */
    rc = SQLITE_ERROR;
  }else if( v==0 ){
    /* If there is no statement handle, then the blob-handle has
    ** already been invalidated. Return SQLITE_ABORT in this case.
    */
    rc = SQLITE_ABORT;
  }else{
    /* Call either BtreeData() or BtreePutData(). If SQLITE_ABORT is
    ** returned, clean-up the statement handle.
    */
    assert( db == v->db );
    sqlite3BtreeEnterCursor(p->pCsr);

#ifdef SQLITE_ENABLE_PREUPDATE_HOOK
    if( xCall==sqlite3BtreePutData && db->xPreUpdateCallback ){
      /* If a pre-update hook is registered and this is a write cursor, 
      ** invoke it here. 
      ** 
      ** TODO: The preupdate-hook is passed SQLITE_DELETE, even though this
      ** operation should really be an SQLITE_UPDATE. This is probably
      ** incorrect, but is convenient because at this point the new.* values 
      ** are not easily obtainable. And for the sessions module, an 
      ** SQLITE_UPDATE where the PK columns do not change is handled in the 
      ** same way as an SQLITE_DELETE (the SQLITE_DELETE code is actually
      ** slightly more efficient). Since you cannot write to a PK column
      ** using the incremental-blob API, this works. For the sessions module
      ** anyhow.
      */
      sqlite3_int64 iKey;
      iKey = sqlite3BtreeIntegerKey(p->pCsr);
      sqlite3VdbePreUpdateHook(
          v, v->apCsr[0], SQLITE_DELETE, p->zDb, p->pTab, iKey, -1
      );
    }
#endif

    rc = xCall(p->pCsr, iOffset+p->iOffset, n, z);
    sqlite3BtreeLeaveCursor(p->pCsr);
    if( rc==SQLITE_ABORT ){
      sqlite3VdbeFinalize(v);
      p->pStmt = 0;
    }else{
      v->rc = rc;
    }
  }
  sqlite3Error(db, rc);
  rc = sqlite3ApiExit(db, rc);
  sqlite3_mutex_leave(db->mutex);
  return rc;
}

// Assembly:
testq %rdi, %rdi
je 0x40cf2b
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x18, %rsp
movl %ecx, %r15d
movl %edx, %r13d
movq %rsi, %r12
movq %rdi, %r14
movq %r8, 0x10(%rsp)
movq 0x20(%rdi), %rbx
movq 0x18(%rbx), %rdi
testq %rdi, %rdi
je 0x40ceb1
callq *0x18630f(%rip)         # 0x5931c0
pushq $0x1
popq %rbp
movl %r15d, %eax
orl %r13d, %eax
js 0x40cf41
movl %r15d, %eax
movl %r13d, %ecx
addq %rax, %rcx
movslq (%r14), %rax
cmpq %rax, %rcx
jg 0x40cf41
movq 0x18(%r14), %rax
pushq $0x4
popq %rbp
testq %rax, %rax
je 0x40cf41
movq %rax, 0x8(%rsp)
movq 0x10(%r14), %rax
movq 0x8(%rax), %rdi
callq 0x4083c8
movq 0x10(%r14), %rdi
addl 0x4(%r14), %r15d
movl %r15d, %esi
movl %r13d, %edx
movq %r12, %rcx
callq *0x10(%rsp)
movl %eax, %r15d
movq 0x10(%r14), %rax
movq 0x8(%rax), %rdi
callq 0x4092a1
cmpl $0x4, %r15d
jne 0x40cf35
movq 0x8(%rsp), %rdi
callq 0x4097b2
andq $0x0, 0x18(%r14)
jmp 0x40cf41
movl $0x16200, %edi          # imm = 0x16200
jmp 0x403dfd
movq 0x8(%rsp), %rax
movl %r15d, 0x38(%rax)
movl %r15d, %ebp
movq %rbx, %rdi
movl %ebp, %esi
callq 0x407da3
movq %rbx, %rdi
movl %ebp, %esi
callq 0x4097e6
movl %eax, %ebp
movq 0x18(%rbx), %rdi
testq %rdi, %rdi
je 0x40cf66
callq *0x18626a(%rip)         # 0x5931d0
movl %ebp, %eax
addq $0x18, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq