Stream.cpp revision 6a61141137c7a46d747aa611c9caf62436bc119f
1a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik/* 2a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik * Copyright (C) 2013 The Android Open Source Project 3a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik * 4a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik * Licensed under the Apache License, Version 2.0 (the "License"); 5a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik * you may not use this file except in compliance with the License. 6a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik * You may obtain a copy of the License at 7a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik * 8a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik * http://www.apache.org/licenses/LICENSE-2.0 9a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik * 10a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik * Unless required by applicable law or agreed to in writing, software 11a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik * distributed under the License is distributed on an "AS IS" BASIS, 12a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik * See the License for the specific language governing permissions and 14a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik * limitations under the License. 15a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik */ 16a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik 17a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik#define LOG_TAG "Stream" 18a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik 19a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik#include "Stream.h" 20a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik 21a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik#include <string.h> 22a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik 23a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik#include "JNIHelpers.h" 24a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik#include "utils/log.h" 25a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik#include "utils/math.h" 26a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik 27a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craikstatic struct { 28a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik jmethodID read; 29a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik jmethodID reset; 30a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik} gInputStreamClassInfo; 31a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik 32a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris CraikStream::Stream() 33a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik : mPeekBuffer(0) 34a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik , mPeekSize(0) 35a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik , mPeekOffset(0) { 36a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik} 37a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik 38a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris CraikStream::~Stream() { 39a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik delete mPeekBuffer; 40a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik} 41a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik 42a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craiksize_t Stream::peek(void* buffer, size_t size) { 43a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik size_t peek_remaining = mPeekSize - mPeekOffset; 44a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik if (size > peek_remaining) { 45a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik char* old_peek = mPeekBuffer; 46a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik mPeekBuffer = new char[size]; 47a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik if (old_peek) { 48a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik memcpy(mPeekBuffer, old_peek + mPeekOffset, peek_remaining); 49a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik delete old_peek; 50a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik } 51a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik size_t read = doRead(mPeekBuffer + mPeekOffset, size - peek_remaining); 52a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik mPeekOffset = 0; 53a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik mPeekSize = peek_remaining + read; 54a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik } 55a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik size = min(size, mPeekSize - mPeekOffset); 56a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik memcpy(buffer, mPeekBuffer + mPeekOffset, size); 57a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik return size; 58a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik} 59a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik 60a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craiksize_t Stream::read(void* buffer, size_t size) { 61a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik size_t bytes_read = 0; 62a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik size_t peek_remaining = mPeekSize - mPeekOffset; 63a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik if (peek_remaining) { 64a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik bytes_read = min(size, peek_remaining); 65a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik memcpy(buffer, mPeekBuffer + mPeekOffset, bytes_read); 66a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik mPeekOffset += bytes_read; 67a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik if (mPeekOffset == mPeekSize) { 68a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik delete mPeekBuffer; 69a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik mPeekBuffer = 0; 70a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik mPeekOffset = 0; 71a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik mPeekSize = 0; 72a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik } 73a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik size -= bytes_read; 74a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik buffer = ((char*) buffer) + bytes_read; 75a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik } 76a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik if (size) { 77a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik bytes_read += doRead(buffer, size); 78a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik } 79a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik return bytes_read; 80a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik} 81a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik 826a61141137c7a46d747aa611c9caf62436bc119fChris Craikuint8_t* Stream::getRawBufferAddr() { 836a61141137c7a46d747aa611c9caf62436bc119fChris Craik return NULL; 846a61141137c7a46d747aa611c9caf62436bc119fChris Craik} 856a61141137c7a46d747aa611c9caf62436bc119fChris Craik 866a61141137c7a46d747aa611c9caf62436bc119fChris Craikjobject Stream::getRawBuffer() { 876a61141137c7a46d747aa611c9caf62436bc119fChris Craik return NULL; 886a61141137c7a46d747aa611c9caf62436bc119fChris Craik} 896a61141137c7a46d747aa611c9caf62436bc119fChris Craik 906a61141137c7a46d747aa611c9caf62436bc119fChris Craikint Stream::getRawBufferSize() { 916a61141137c7a46d747aa611c9caf62436bc119fChris Craik return 0; 926a61141137c7a46d747aa611c9caf62436bc119fChris Craik} 936a61141137c7a46d747aa611c9caf62436bc119fChris Craik 946a61141137c7a46d747aa611c9caf62436bc119fChris Craikuint8_t* MemoryStream::getRawBufferAddr() { 956a61141137c7a46d747aa611c9caf62436bc119fChris Craik return mBuffer; 966a61141137c7a46d747aa611c9caf62436bc119fChris Craik} 976a61141137c7a46d747aa611c9caf62436bc119fChris Craik 986a61141137c7a46d747aa611c9caf62436bc119fChris Craikjobject MemoryStream::getRawBuffer() { 996a61141137c7a46d747aa611c9caf62436bc119fChris Craik return mRawBuffer; 1006a61141137c7a46d747aa611c9caf62436bc119fChris Craik} 1016a61141137c7a46d747aa611c9caf62436bc119fChris Craik 1026a61141137c7a46d747aa611c9caf62436bc119fChris Craikint MemoryStream::getRawBufferSize() { 1036a61141137c7a46d747aa611c9caf62436bc119fChris Craik if (mRawBuffer != NULL) { 1046a61141137c7a46d747aa611c9caf62436bc119fChris Craik return mRemaining; 1056a61141137c7a46d747aa611c9caf62436bc119fChris Craik } else { 1066a61141137c7a46d747aa611c9caf62436bc119fChris Craik return 0; 1076a61141137c7a46d747aa611c9caf62436bc119fChris Craik } 1086a61141137c7a46d747aa611c9caf62436bc119fChris Craik} 1096a61141137c7a46d747aa611c9caf62436bc119fChris Craik 110a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craiksize_t MemoryStream::doRead(void* buffer, size_t size) { 111a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik size = min(size, mRemaining); 112a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik memcpy(buffer, mBuffer, size); 113a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik mBuffer += size; 114a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik mRemaining -= size; 115a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik return size; 116a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik} 117a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik 118a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craiksize_t FileStream::doRead(void* buffer, size_t size) { 119a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik return fread(buffer, 1, size, mFd); 120a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik} 121a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik 122a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craiksize_t JavaInputStream::doRead(void* dstBuffer, size_t size) { 123a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik size_t totalBytesRead = 0; 124a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik 125a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik do { 126a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik size_t requested = min(size, mByteArrayLength); 127a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik 128a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik jint bytesRead = mEnv->CallIntMethod(mInputStream, 129a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik gInputStreamClassInfo.read, mByteArray, 0, requested); 130a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik if (mEnv->ExceptionCheck() || bytesRead < 0) { 131a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik return 0; 132a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik } 133a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik 134a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik mEnv->GetByteArrayRegion(mByteArray, 0, bytesRead, (jbyte*)dstBuffer); 135a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik dstBuffer = (char*)dstBuffer + bytesRead; 136a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik totalBytesRead += bytesRead; 137a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik size -= bytesRead; 138a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik } while (size > 0); 139a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik 140a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik return totalBytesRead; 141a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik} 142a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik 143a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craikjint JavaStream_OnLoad(JNIEnv* env) { 144a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik // Skip the verbose logging on error for these, as they won't be subject 145a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik // to obfuscators or similar and are thus unlikely to ever fail 146a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik jclass inputStreamClazz = env->FindClass("java/io/InputStream"); 147a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik if (!inputStreamClazz) { 148a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik return -1; 149a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik } 150a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik gInputStreamClassInfo.read = env->GetMethodID(inputStreamClazz, "read", "([BII)I"); 151a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik gInputStreamClassInfo.reset = env->GetMethodID(inputStreamClazz, "reset", "()V"); 152a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik if (!gInputStreamClassInfo.read || !gInputStreamClassInfo.reset) { 153a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik return -1; 154a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik } 155a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik return 0; 156a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik} 157