// Tests reading the stream across boundaries of what has been buffered so far and what // the total buffer size is. static void test_incremental_buffering(skiatest::Reporter* reporter, size_t bufferSize) { // NOTE: For this and other tests in this file, we cheat and continue to refer to the // wrapped stream, but that's okay because we know the wrapping stream has not been // deleted yet (and we only call const methods in it). SkMemoryStream* memStream = SkNEW_ARGS(SkMemoryStream, (gAbcs, strlen(gAbcs), false)); SkAutoTDelete<SkStream> bufferedStream(SkFrontBufferedStream::Create(memStream, bufferSize)); test_hasLength(reporter, *bufferedStream.get(), *memStream); // First, test reading less than the max buffer size. test_read(reporter, bufferedStream, gAbcs, bufferSize / 2); // Now test rewinding back to the beginning and reading less than what was // already buffered. test_rewind(reporter, bufferedStream, true); test_read(reporter, bufferedStream, gAbcs, bufferSize / 4); // Now test reading part of what was buffered, and buffering new data. test_read(reporter, bufferedStream, gAbcs + bufferedStream->getPosition(), bufferSize / 2); // Now test reading what was buffered, buffering new data, and // reading directly from the stream. test_rewind(reporter, bufferedStream, true); test_read(reporter, bufferedStream, gAbcs, bufferSize << 1); // We have reached the end of the buffer, so rewinding will fail. // This test assumes that the stream is larger than the buffer; otherwise the // result of rewind should be true. test_rewind(reporter, bufferedStream, false); }
ECode Movie::NativeDecodeStream( /* [in] */ IInputStream* istream, /* [out] */IMovie** movie) { VALIDATE_NOT_NULL(movie); // NPE_CHECK_RETURN_ZERO(env, istream); if (istream == NULL) { *movie = NULL; return NOERROR; } AutoPtr<ArrayOf<Byte> > byteArray = ArrayOf<Byte>::Alloc(16*1024); // ScopedLocalRef<jbyteArray> scoper(env, byteArray); SkStream* strm = CreateInputStreamAdaptor(istream, byteArray); if (NULL == strm) { *movie = NULL; return NOERROR; } // Need to buffer enough input to be able to rewind as much as might be read by a decoder // trying to determine the stream's format. The only decoder for movies is GIF, which // will only read 6. // FIXME: Get this number from SkImageDecoder SkAutoTUnref<SkStreamRewindable> bufferedStream(SkFrontBufferedStream::Create(strm, 6)); SkASSERT(bufferedStream.get() != NULL); SkMovie* moov = SkMovie::DecodeStream(bufferedStream); strm->unref(); return CreateMovie(moov, movie); }
// Test using a stream with an initial offset. static void test_initial_offset(skiatest::Reporter* reporter, size_t bufferSize) { SkMemoryStream* memStream = new SkMemoryStream(gAbcs, strlen(gAbcs), false); // Skip a few characters into the memStream, so that bufferedStream represents an offset into // the stream it wraps. const size_t arbitraryOffset = 17; memStream->skip(arbitraryOffset); std::unique_ptr<SkStream> bufferedStream(SkFrontBufferedStream::Create(memStream, bufferSize)); // Since SkMemoryStream has a length, bufferedStream must also. REPORTER_ASSERT(reporter, bufferedStream->hasLength()); const size_t amountToRead = 10; const size_t bufferedLength = bufferedStream->getLength(); size_t currentPosition = 0; // Read the stream in chunks. After each read, the position must match currentPosition, // which sums the amount attempted to read, unless the end of the stream has been reached. // Importantly, the end should not have been reached until currentPosition == bufferedLength. while (currentPosition < bufferedLength) { REPORTER_ASSERT(reporter, !bufferedStream->isAtEnd()); test_read(reporter, bufferedStream.get(), gAbcs + arbitraryOffset + currentPosition, amountToRead); currentPosition = SkTMin(currentPosition + amountToRead, bufferedLength); REPORTER_ASSERT(reporter, memStream->getPosition() - arbitraryOffset == currentPosition); } REPORTER_ASSERT(reporter, bufferedStream->isAtEnd()); REPORTER_ASSERT(reporter, bufferedLength == currentPosition); }
void VStreamsUnit::_testWriteBufferedStream() { // Test VWriteBufferedStream. We'll have it buffer to a (another) // memory stream so we don't have to use a file. We'll write some // text to it and verify it. We'll seek and skip. VMemoryStream rawStream; VWriteBufferedStream bufferedStream(rawStream); VBinaryIOStream io(bufferedStream); io.writeS32(1234); io.writeS32(5678); io.seek(CONST_S64(-4), SEEK_CUR); io.writeS32(9012); io.writeS32(3456); io.flush(); VUNIT_ASSERT_EQUAL_LABELED(rawStream.getIOOffset(), CONST_S64(12), "write-buffered stream offset"); io.writeS32(7890); io.writeS32(2468); io.flush(); VUNIT_ASSERT_EQUAL_LABELED(rawStream.getIOOffset(), CONST_S64(20), "write-buffered stream offset"); VBinaryIOStream verifier(rawStream); verifier.seek0(); VUNIT_ASSERT_EQUAL_LABELED(verifier.readS32(), 1234, "write-buffered stream check 1"); VUNIT_ASSERT_EQUAL_LABELED(verifier.readS32(), 9012, "write-buffered stream check 2"); VUNIT_ASSERT_EQUAL_LABELED(verifier.readS32(), 3456, "write-buffered stream check 3"); VUNIT_ASSERT_EQUAL_LABELED(verifier.readS32(), 7890, "write-buffered stream check 4"); VUNIT_ASSERT_EQUAL_LABELED(verifier.readS32(), 2468, "write-buffered stream check 5"); }
static void test_peeking_front_buffered_stream(skiatest::Reporter* r, const SkStream& original, size_t bufferSize) { SkStream* dupe = original.duplicate(); REPORTER_ASSERT(r, dupe != NULL); SkAutoTDelete<SkStream> bufferedStream(SkFrontBufferedStream::Create(dupe, bufferSize)); REPORTER_ASSERT(r, bufferedStream != NULL); test_peeking_stream(r, bufferedStream, bufferSize); }
static void test_peeking_front_buffered_stream(skiatest::Reporter* r, const SkStream& original, size_t bufferSize) { SkStream* dupe = original.duplicate(); REPORTER_ASSERT(r, dupe != nullptr); SkAutoTDelete<SkStream> bufferedStream(SkFrontBufferedStream::Create(dupe, bufferSize)); REPORTER_ASSERT(r, bufferedStream != nullptr); size_t peeked = 0; for (size_t i = 1; !bufferedStream->isAtEnd(); i++) { const size_t unpeekableBytes = compare_peek_to_read(r, bufferedStream, i); if (unpeekableBytes > 0) { // This could not have returned a number greater than i. REPORTER_ASSERT(r, unpeekableBytes <= i); // We have reached the end of the buffer. Verify that it was at least // bufferSize. REPORTER_ASSERT(r, peeked + i - unpeekableBytes >= bufferSize); // No more peeking is supported. break; } peeked += i; } // Test that attempting to peek beyond the length of the buffer does not prevent rewinding. bufferedStream.reset(SkFrontBufferedStream::Create(original.duplicate(), bufferSize)); REPORTER_ASSERT(r, bufferedStream != nullptr); const size_t bytesToPeek = bufferSize + 1; SkAutoMalloc peekStorage(bytesToPeek); SkAutoMalloc readStorage(bytesToPeek); for (size_t start = 0; start <= bufferSize; start++) { // Skip to the starting point REPORTER_ASSERT(r, bufferedStream->skip(start) == start); const size_t bytesPeeked = bufferedStream->peek(peekStorage.get(), bytesToPeek); if (0 == bytesPeeked) { // Peeking should only fail completely if we have read/skipped beyond the buffer. REPORTER_ASSERT(r, start >= bufferSize); break; } // Only read the amount that was successfully peeked. const size_t bytesRead = bufferedStream->read(readStorage.get(), bytesPeeked); REPORTER_ASSERT(r, bytesRead == bytesPeeked); REPORTER_ASSERT(r, !memcmp(peekStorage.get(), readStorage.get(), bytesPeeked)); // This should be safe to rewind. REPORTER_ASSERT(r, bufferedStream->rewind()); } }
// This test ensures that buffering the exact length of the stream and attempting to read beyond it // does not invalidate the buffer. static void test_read_beyond_buffer(skiatest::Reporter* reporter, size_t bufferSize) { // Use a stream that behaves like Android's stream. AndroidLikeMemoryStream* memStream = new AndroidLikeMemoryStream((void*)gAbcs, bufferSize, false); // Create a buffer that matches the length of the stream. std::unique_ptr<SkStream> bufferedStream(SkFrontBufferedStream::Create(memStream, bufferSize)); test_hasLength(reporter, *bufferedStream.get(), *memStream); // Attempt to read one more than the bufferSize test_read(reporter, bufferedStream.get(), gAbcs, bufferSize + 1); test_rewind(reporter, bufferedStream.get(), true); // Ensure that the initial read did not invalidate the buffer. test_read(reporter, bufferedStream.get(), gAbcs, bufferSize); }
static void test_perfectly_sized_buffer(skiatest::Reporter* reporter, size_t bufferSize) { SkMemoryStream* memStream = SkNEW_ARGS(SkMemoryStream, (gAbcs, strlen(gAbcs), false)); SkAutoTDelete<SkStream> bufferedStream(SkFrontBufferedStream::Create(memStream, bufferSize)); test_hasLength(reporter, *bufferedStream.get(), *memStream); // Read exactly the amount that fits in the buffer. test_read(reporter, bufferedStream, gAbcs, bufferSize); // Rewinding should succeed. test_rewind(reporter, bufferedStream, true); // Once again reading buffered info should succeed test_read(reporter, bufferedStream, gAbcs, bufferSize); // Read past the size of the buffer. At this point, we cannot return. test_read(reporter, bufferedStream, gAbcs + bufferedStream->getPosition(), 1); test_rewind(reporter, bufferedStream, false); }
static void test_skipping(skiatest::Reporter* reporter, size_t bufferSize) { SkMemoryStream* memStream = SkNEW_ARGS(SkMemoryStream, (gAbcs, strlen(gAbcs), false)); SkAutoTDelete<SkStream> bufferedStream(SkFrontBufferedStream::Create(memStream, bufferSize)); test_hasLength(reporter, *bufferedStream.get(), *memStream); // Skip half the buffer. bufferedStream->skip(bufferSize / 2); // Rewind, then read part of the buffer, which should have been read. test_rewind(reporter, bufferedStream, true); test_read(reporter, bufferedStream, gAbcs, bufferSize / 4); // Now skip beyond the buffered piece, but still within the total buffer. bufferedStream->skip(bufferSize / 2); // Test that reading will still work. test_read(reporter, bufferedStream, gAbcs + bufferedStream->getPosition(), bufferSize / 4); test_rewind(reporter, bufferedStream, true); test_read(reporter, bufferedStream, gAbcs, bufferSize); }
static jobject movie_decodeStream(JNIEnv* env, jobject clazz, jobject istream) { NPE_CHECK_RETURN_ZERO(env, istream); jbyteArray byteArray = env->NewByteArray(16*1024); ScopedLocalRef<jbyteArray> scoper(env, byteArray); SkStream* strm = CreateJavaInputStreamAdaptor(env, istream, byteArray); if (NULL == strm) { return 0; } // Need to buffer enough input to be able to rewind as much as might be read by a decoder // trying to determine the stream's format. The only decoder for movies is GIF, which // will only read 6. // FIXME: Get this number from SkImageDecoder SkAutoTUnref<SkStreamRewindable> bufferedStream(SkFrontBufferedStream::Create(strm, 6)); SkASSERT(bufferedStream.get() != NULL); SkMovie* moov = SkMovie::DecodeStream(bufferedStream); strm->unref(); return create_jmovie(env, moov); }
// GenerateMachineCode may modify the Module object passed in. Should we clone it first? void GenerateMachineCode(llvm::raw_ostream& os, IRModuleEmitter& moduleEmitter, OutputFileType fileType, const MachineCodeOutputOptions& ellOptions) { llvm::Module& module = *(moduleEmitter.GetLLVMModule()); llvm::LLVMContext context; context.setDiscardValueNames(false); // Don't throw away names of non-global values // Verify module if requested if (ellOptions.verifyModule && llvm::verifyModule(module)) { throw EmitterException(EmitterError::unexpected, "Module verification failed"); } // Set the triple for the module, and retrieve it as a Triple object auto targetTripleStr = ellOptions.targetDevice.triple.empty() ? llvm::sys::getDefaultTargetTriple() : ellOptions.targetDevice.triple; module.setTargetTriple(llvm::Triple::normalize(targetTripleStr)); llvm::Triple targetTriple{ module.getTargetTriple() }; // Get the target-specific parser. Note that targetTriple can be modified by lookupTarget. std::string error; const llvm::Target* target = llvm::TargetRegistry::lookupTarget(ellOptions.targetDevice.architecture, targetTriple, error); if (!target) { throw EmitterException(EmitterError::unexpected, std::string("Couldn't create target ") + error); } llvm::TargetOptions targetOptions = MakeTargetOptions(); targetOptions.MCOptions.AsmVerbose = ellOptions.verboseOutput; targetOptions.FloatABIType = ellOptions.floatABI; llvm::Reloc::Model relocModel = llvm::Reloc::Static; llvm::CodeModel::Model codeModel = llvm::CodeModel::Default; std::unique_ptr<llvm::TargetMachine> targetMachine(target->createTargetMachine(targetTriple.getTriple(), ellOptions.targetDevice.cpu, ellOptions.targetDevice.features, targetOptions, relocModel, codeModel, ellOptions.optimizationLevel)); if (!targetMachine) { throw EmitterException(EmitterError::unexpected, "Unable to allocate target machine"); } // Build up all of the passes that we want to apply to the module llvm::legacy::PassManager passManager; // Get a targetLibraryInfo describing the library functions available for this triple, // and any special processing we might want to do. For instance, if we want to // disable all builtin library functions, do this: `targetLibraryInfo.disableAllFunctions();` llvm::TargetLibraryInfoImpl targetLibraryInfo(llvm::Triple(module.getTargetTriple())); // ...and add it to the pass manager, so various optimizations can be done passManager.add(new llvm::TargetLibraryInfoWrapperPass(targetLibraryInfo)); // Set the data layout of the module to match the target machine module.setDataLayout(targetMachine->createDataLayout()); // Override function attributes based on cpu and features if (ellOptions.targetDevice.cpu != "") { SetFunctionAttributes(ellOptions.targetDevice.cpu, ellOptions.targetDevice.features, module); } // Set up passes to emit code to a memory stream llvm::SmallVector<char, 0> buffer; llvm::raw_svector_ostream bufferedStream(buffer); if (targetMachine->addPassesToEmitFile(passManager, bufferedStream, fileType, ellOptions.verifyModule, nullptr, nullptr, nullptr, nullptr)) { throw EmitterException(EmitterError::unexpected, "target does not support generation of this file type!"); } // Finally, run the passes to emit code to the straem passManager.run(module); // run() returns a bool indicating if the module was modified (true if it was) if (moduleEmitter.GetDiagnosticHandler().HadError()) { throw EmitterException(EmitterError::unexpected, "Error compiling module"); } // Write memory buffer to our output stream os << buffer; }