}
}
+SizeT ML_(img_get_some)(/*OUT*/void* dst,
+ DiImage* img, DiOffT offset, SizeT size)
+{
+ vg_assert(img);
+ vg_assert(size > 0);
+ vg_assert(ML_(img_valid)(img, offset, size));
+ UChar* dstU = (UChar*)dst;
+ /* Use |get| in the normal way to get the first byte of the range.
+ This guarantees to put the cache entry containing |offset| in
+ position zero. */
+ dstU[0] = get(img, offset);
+ /* Now just read as many bytes as we can (or need) directly out of
+ entry zero, without bothering to call |get| each time. */
+ CEnt* ce = img->ces[0];
+ vg_assert(ce && ce->used >= 1);
+ vg_assert(is_in_CEnt(ce, offset));
+ SizeT nToCopy = size - 1;
+ SizeT nAvail = (SizeT)(ce->used - (offset + 1 - ce->off));
+ vg_assert(nAvail >= 0 && nAvail <= ce->used-1);
+ if (nAvail < nToCopy) nToCopy = nAvail;
+ VG_(memcpy)(&dstU[1], &ce->data[offset + 1 - ce->off], nToCopy);
+ return nToCopy + 1;
+}
+
+
SizeT ML_(img_strlen)(DiImage* img, DiOffT off)
{
vg_assert(ML_(img_valid)(img, off, 1));
vg_assert(avail > 0 && avail <= img_szB);
if (avail > 1024) avail = 1024;
UChar buf[1024];
- ML_(img_get)(buf, img, curr_off, avail);
+ SizeT nGot = ML_(img_get_some)(buf, img, curr_off, avail);
+ vg_assert(nGot >= 1 && nGot <= avail);
UInt i;
- for (i = 0; i < (UInt)avail; i++)
+ for (i = 0; i < (UInt)nGot; i++)
crc = crc32_table[(crc ^ buf[i]) & 0xff] ^ (crc >> 8);
- curr_off += avail;
+ curr_off += nGot;
}
return ~crc & 0xFFFFFFFF;
} else {
void ML_(img_get)(/*OUT*/void* dst,
DiImage* img, DiOffT offset, SizeT size);
+/* A version of ML_(img_get) that is significantly cheaper when
+ fetching a lot of data, at the cost of being more difficult to use.
+ Fetches between 1 and |size| bytes from |img| at |offset| and
+ places them in |dst|. |size| must be at least 1. The number of
+ bytes read is returned, and the caller must be able to deal with
+ any number between 1 and |size|. |offset| must be a valid offset
+ in the image; if not the function will not return. This function
+ will not read off the end of the image. */
+SizeT ML_(img_get_some)(/*OUT*/void* dst,
+ DiImage* img, DiOffT offset, SizeT size);
+
/* Copy a C string out of the image, into ML_(dinfo_zalloc)'d space.
The caller owns the string and must free it with ML_(dinfo_free).
|offset| may be DiOffT_INVALID, in which case this returns NULL. */