in java/JavaInputStream.h [51:114]
virtual long long read(char *buffer, long long bytesToRead) {
jmethodID readMethod = env->GetMethodID(
env->FindClass("java/io/InputStream"), "read", "([BII)I");
if (!readMethod) {
throw std::runtime_error("Native code failed to find "
"java.io.InputStream#read(byte[]) method!");
}
long long bytesRead = 0;
long long bufferSize = std::min(MAX_BUFFER_SIZE, bytesToRead);
jbyteArray byteArray = env->NewByteArray(bufferSize);
if (!byteArray) {
throw std::domain_error(
"Failed to instantiate Java byte array of size: " +
std::to_string(bufferSize));
}
if (peekValue.size()) {
long long bytesToCopy =
std::min(bytesToRead, (long long)peekValue.size());
std::memcpy(buffer, peekValue.data(), bytesToCopy);
for (int i = 0; i < bytesToCopy; i++)
peekValue.erase(peekValue.begin());
bytesRead += bytesToCopy;
buffer += bytesToCopy;
}
while (bytesRead < bytesToRead) {
int readResult = env->CallIntMethod(
inputStream, readMethod, byteArray, 0,
(int)(std::min(bufferSize, bytesToRead - bytesRead)));
if (env->ExceptionCheck()) {
return 0;
}
if (readResult > 0) {
if (bytesRead + readResult > bytesToRead) {
throw std::domain_error("java.io.InputStream#read(byte[]) returned " +
std::to_string(readResult) + ", but only " +
std::to_string(bytesToRead - bytesRead) +
" bytes were required.");
}
if (readResult > bufferSize) {
throw std::domain_error("java.io.InputStream#read(byte[]) returned " +
std::to_string(readResult) +
", but buffer is only " +
std::to_string(bufferSize) + " bytes.");
}
env->GetByteArrayRegion(byteArray, 0, readResult, (jbyte *)buffer);
bytesRead += readResult;
buffer += readResult;
} else {
bytesRead = readResult;
break;
}
}
env->DeleteLocalRef(byteArray);
return bytesRead;
}