1/*
2 * Copyright 2015 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#include "JavaInputStream.h"
9
10JavaInputStream::JavaInputStream(
11        JNIEnv* env, jbyteArray javaBuffer, jobject inputStream)
12    : fEnv(env)
13    , fStartIndex(0)
14    , fEndIndex(0) {
15    SkASSERT(inputStream);
16    SkASSERT(javaBuffer);
17    fInputStream = inputStream;
18    fJavaBuffer = javaBuffer;
19    fInputStreamClass = env->FindClass("java/io/InputStream");
20    SkASSERT(fInputStreamClass);
21    fReadMethodID = env->GetMethodID(fInputStreamClass, "read", "([B)I");
22    SkASSERT(fReadMethodID);
23}
24
25bool JavaInputStream::isAtEnd() const { return fStartIndex == fEndIndex; }
26
27size_t JavaInputStream::read(void* voidBuffer, size_t size) {
28    size_t totalRead = 0;
29    char* buffer = static_cast<char*>(voidBuffer);  // may be NULL;
30    while (size) {
31        // make sure the cache has at least one byte or is done.
32        if (fStartIndex == fEndIndex) {
33            jint count =
34                fEnv->CallIntMethod(fInputStream, fReadMethodID, fJavaBuffer);
35            if (fEnv->ExceptionCheck()) {
36                fEnv->ExceptionDescribe();
37                fEnv->ExceptionClear();
38                SkDebugf("---- java.io.InputStream::read() threw an exception\n");
39                return 0;
40            }
41            fStartIndex = 0;
42            fEndIndex = count;
43            if (this->isAtEnd()) {
44                return totalRead;  // No more to read.
45            }
46        }
47        SkASSERT(fEndIndex > fStartIndex);
48        size_t length = SkTMin(SkToSizeT(fEndIndex - fStartIndex), size);
49        if (buffer && length) {
50            jbyte* bufferElements
51                = fEnv->GetByteArrayElements(fJavaBuffer, NULL);
52            memcpy(buffer, &bufferElements[fStartIndex], length);
53            buffer += length;
54            fEnv->ReleaseByteArrayElements(fJavaBuffer, bufferElements, 0);
55        }
56        totalRead += length;
57        size -= length;
58        fStartIndex += length;
59    }
60    return totalRead;
61}
62