virtual long long read()

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;
  }