12880df2609eba09b555ca37be04b6ad89290c765Tom Hudson/*
22880df2609eba09b555ca37be04b6ad89290c765Tom Hudson * Copyright 2015 Google Inc.
32880df2609eba09b555ca37be04b6ad89290c765Tom Hudson *
42880df2609eba09b555ca37be04b6ad89290c765Tom Hudson * Use of this source code is governed by a BSD-style license that can be
52880df2609eba09b555ca37be04b6ad89290c765Tom Hudson * found in the LICENSE file.
62880df2609eba09b555ca37be04b6ad89290c765Tom Hudson */
72880df2609eba09b555ca37be04b6ad89290c765Tom Hudson
82880df2609eba09b555ca37be04b6ad89290c765Tom Hudson#include "JavaInputStream.h"
92880df2609eba09b555ca37be04b6ad89290c765Tom Hudson
102880df2609eba09b555ca37be04b6ad89290c765Tom HudsonJavaInputStream::JavaInputStream(
112880df2609eba09b555ca37be04b6ad89290c765Tom Hudson        JNIEnv* env, jbyteArray javaBuffer, jobject inputStream)
122880df2609eba09b555ca37be04b6ad89290c765Tom Hudson    : fEnv(env)
132880df2609eba09b555ca37be04b6ad89290c765Tom Hudson    , fStartIndex(0)
142880df2609eba09b555ca37be04b6ad89290c765Tom Hudson    , fEndIndex(0) {
152880df2609eba09b555ca37be04b6ad89290c765Tom Hudson    SkASSERT(inputStream);
162880df2609eba09b555ca37be04b6ad89290c765Tom Hudson    SkASSERT(javaBuffer);
172880df2609eba09b555ca37be04b6ad89290c765Tom Hudson    fInputStream = inputStream;
182880df2609eba09b555ca37be04b6ad89290c765Tom Hudson    fJavaBuffer = javaBuffer;
192880df2609eba09b555ca37be04b6ad89290c765Tom Hudson    fInputStreamClass = env->FindClass("java/io/InputStream");
202880df2609eba09b555ca37be04b6ad89290c765Tom Hudson    SkASSERT(fInputStreamClass);
212880df2609eba09b555ca37be04b6ad89290c765Tom Hudson    fReadMethodID = env->GetMethodID(fInputStreamClass, "read", "([B)I");
222880df2609eba09b555ca37be04b6ad89290c765Tom Hudson    SkASSERT(fReadMethodID);
232880df2609eba09b555ca37be04b6ad89290c765Tom Hudson}
242880df2609eba09b555ca37be04b6ad89290c765Tom Hudson
252880df2609eba09b555ca37be04b6ad89290c765Tom Hudsonbool JavaInputStream::isAtEnd() const { return fStartIndex == fEndIndex; }
262880df2609eba09b555ca37be04b6ad89290c765Tom Hudson
272880df2609eba09b555ca37be04b6ad89290c765Tom Hudsonsize_t JavaInputStream::read(void* voidBuffer, size_t size) {
282880df2609eba09b555ca37be04b6ad89290c765Tom Hudson    size_t totalRead = 0;
292880df2609eba09b555ca37be04b6ad89290c765Tom Hudson    char* buffer = static_cast<char*>(voidBuffer);  // may be NULL;
302880df2609eba09b555ca37be04b6ad89290c765Tom Hudson    while (size) {
312880df2609eba09b555ca37be04b6ad89290c765Tom Hudson        // make sure the cache has at least one byte or is done.
322880df2609eba09b555ca37be04b6ad89290c765Tom Hudson        if (fStartIndex == fEndIndex) {
332880df2609eba09b555ca37be04b6ad89290c765Tom Hudson            jint count =
342880df2609eba09b555ca37be04b6ad89290c765Tom Hudson                fEnv->CallIntMethod(fInputStream, fReadMethodID, fJavaBuffer);
352880df2609eba09b555ca37be04b6ad89290c765Tom Hudson            if (fEnv->ExceptionCheck()) {
362880df2609eba09b555ca37be04b6ad89290c765Tom Hudson                fEnv->ExceptionDescribe();
372880df2609eba09b555ca37be04b6ad89290c765Tom Hudson                fEnv->ExceptionClear();
382880df2609eba09b555ca37be04b6ad89290c765Tom Hudson                SkDebugf("---- java.io.InputStream::read() threw an exception\n");
392880df2609eba09b555ca37be04b6ad89290c765Tom Hudson                return 0;
402880df2609eba09b555ca37be04b6ad89290c765Tom Hudson            }
412880df2609eba09b555ca37be04b6ad89290c765Tom Hudson            fStartIndex = 0;
422880df2609eba09b555ca37be04b6ad89290c765Tom Hudson            fEndIndex = count;
432880df2609eba09b555ca37be04b6ad89290c765Tom Hudson            if (this->isAtEnd()) {
442880df2609eba09b555ca37be04b6ad89290c765Tom Hudson                return totalRead;  // No more to read.
452880df2609eba09b555ca37be04b6ad89290c765Tom Hudson            }
462880df2609eba09b555ca37be04b6ad89290c765Tom Hudson        }
472880df2609eba09b555ca37be04b6ad89290c765Tom Hudson        SkASSERT(fEndIndex > fStartIndex);
482880df2609eba09b555ca37be04b6ad89290c765Tom Hudson        size_t length = SkTMin(SkToSizeT(fEndIndex - fStartIndex), size);
492880df2609eba09b555ca37be04b6ad89290c765Tom Hudson        if (buffer && length) {
502880df2609eba09b555ca37be04b6ad89290c765Tom Hudson            jbyte* bufferElements
512880df2609eba09b555ca37be04b6ad89290c765Tom Hudson                = fEnv->GetByteArrayElements(fJavaBuffer, NULL);
522880df2609eba09b555ca37be04b6ad89290c765Tom Hudson            memcpy(buffer, &bufferElements[fStartIndex], length);
532880df2609eba09b555ca37be04b6ad89290c765Tom Hudson            buffer += length;
542880df2609eba09b555ca37be04b6ad89290c765Tom Hudson            fEnv->ReleaseByteArrayElements(fJavaBuffer, bufferElements, 0);
552880df2609eba09b555ca37be04b6ad89290c765Tom Hudson        }
562880df2609eba09b555ca37be04b6ad89290c765Tom Hudson        totalRead += length;
572880df2609eba09b555ca37be04b6ad89290c765Tom Hudson        size -= length;
582880df2609eba09b555ca37be04b6ad89290c765Tom Hudson        fStartIndex += length;
592880df2609eba09b555ca37be04b6ad89290c765Tom Hudson    }
602880df2609eba09b555ca37be04b6ad89290c765Tom Hudson    return totalRead;
612880df2609eba09b555ca37be04b6ad89290c765Tom Hudson}
62