diff options
Diffstat (limited to 'Build/source/libs/poppler/poppler-0.18.0/poppler/CachedFile.cc')
-rw-r--r-- | Build/source/libs/poppler/poppler-0.18.0/poppler/CachedFile.cc | 256 |
1 files changed, 256 insertions, 0 deletions
diff --git a/Build/source/libs/poppler/poppler-0.18.0/poppler/CachedFile.cc b/Build/source/libs/poppler/poppler-0.18.0/poppler/CachedFile.cc new file mode 100644 index 00000000000..393383006b0 --- /dev/null +++ b/Build/source/libs/poppler/poppler-0.18.0/poppler/CachedFile.cc @@ -0,0 +1,256 @@ +//======================================================================== +// +// CachedFile.cc +// +// This file is licensed under the GPLv2 or later +// +// Copyright 2009 Stefan Thomas <thomas@eload24.com> +// Copyright 2010, 2011 Hib Eris <hib@hiberis.nl> +// Copyright 2010 Albert Astals Cid <aacid@kde.org> +// +//======================================================================== + +#include <config.h> +#include "CachedFile.h" + +//------------------------------------------------------------------------ +// CachedFile +//------------------------------------------------------------------------ + +CachedFile::CachedFile(CachedFileLoader *cachedFileLoaderA, GooString *uriA) +{ + uri = uriA; + loader = cachedFileLoaderA; + + streamPos = 0; + chunks = new std::vector<Chunk>(); + length = 0; + + length = loader->init(uri, this); + refCnt = 1; + + if (length != ((size_t) -1)) { + chunks->resize(length/CachedFileChunkSize + 1); + } + else { + error(-1, "Failed to initialize file cache for '%s'.", uri->getCString()); + chunks->resize(0); + } +} + +CachedFile::~CachedFile() +{ + delete uri; + delete loader; + delete chunks; +} + +void CachedFile::incRefCnt() { + refCnt++; +} + +void CachedFile::decRefCnt() { + if (--refCnt == 0) + delete this; +} + +long int CachedFile::tell() { + return streamPos; +} + +int CachedFile::seek(long int offset, int origin) +{ + if (origin == SEEK_SET) { + streamPos = offset; + } else if (origin == SEEK_CUR) { + streamPos += offset; + } else { + streamPos = length + offset; + } + + if (streamPos > length) { + streamPos = 0; + return 1; + } + + return 0; +} + +int CachedFile::cache(const std::vector<ByteRange> &origRanges) +{ + std::vector<int> loadChunks; + int numChunks = length/CachedFileChunkSize + 1; + std::vector<bool> chunkNeeded(numChunks); + int startChunk, endChunk; + std::vector<ByteRange> chunk_ranges, all; + ByteRange range; + const std::vector<ByteRange> *ranges = &origRanges; + + if (ranges->empty()) { + range.offset = 0; + range.length = length; + all.push_back(range); + ranges = &all; + } + + for (int i = 0; i < numChunks; ++i) + chunkNeeded[i] = false; + for (size_t i = 0; i < ranges->size(); i++) { + + if ((*ranges)[i].length == 0) continue; + if ((*ranges)[i].offset >= length) continue; + + size_t start = (*ranges)[i].offset; + size_t end = start + (*ranges)[i].length - 1; + if (end >= length) end = length - 1; + + startChunk = start / CachedFileChunkSize; + endChunk = end / CachedFileChunkSize; + for (int chunk = startChunk; chunk <= endChunk; chunk++) { + if ((*chunks)[chunk].state == chunkStateNew) { + chunkNeeded[chunk] = true; + } + } + } + + int chunk = 0; + while (chunk < numChunks) { + while (!chunkNeeded[chunk] && (++chunk != numChunks)) ; + if (chunk == numChunks) break; + startChunk = chunk; + loadChunks.push_back(chunk); + + while ((++chunk != numChunks) && chunkNeeded[chunk]) { + loadChunks.push_back(chunk); + } + endChunk = chunk - 1; + + range.offset = startChunk * CachedFileChunkSize; + range.length = (endChunk - startChunk + 1) * CachedFileChunkSize; + + chunk_ranges.push_back(range); + } + + if (chunk_ranges.size() > 0) { + CachedFileWriter writer = + CachedFileWriter(this, &loadChunks); + return loader->load(chunk_ranges, &writer); + } + + return 0; +} + +size_t CachedFile::read(void *ptr, size_t unitsize, size_t count) +{ + size_t bytes = unitsize*count; + if (length < (streamPos + bytes)) { + bytes = length - streamPos; + } + + if (bytes == 0) return 0; + + // Load data + if (cache(streamPos, bytes) != 0) return 0; + + // Copy data to buffer + size_t toCopy = bytes; + while (toCopy) { + int chunk = streamPos / CachedFileChunkSize; + int offset = streamPos % CachedFileChunkSize; + size_t len = CachedFileChunkSize-offset; + + if (len > toCopy) + len = toCopy; + + memcpy(ptr, (*chunks)[chunk].data + offset, len); + streamPos += len; + toCopy -= len; + ptr = (char*)ptr + len; + } + + return bytes; +} + +int CachedFile::cache(size_t offset, size_t length) +{ + std::vector<ByteRange> r; + ByteRange range; + range.offset = offset; + range.length = length; + r.push_back(range); + return cache(r); +} + +//------------------------------------------------------------------------ +// CachedFileWriter +//------------------------------------------------------------------------ + +CachedFileWriter::CachedFileWriter(CachedFile *cachedFileA, std::vector<int> *chunksA) +{ + cachedFile = cachedFileA; + chunks = chunksA; + + if (chunks) { + offset = 0; + it = (*chunks).begin(); + } +} + +CachedFileWriter::~CachedFileWriter() +{ +} + +size_t CachedFileWriter::write(const char *ptr, size_t size) +{ + const char *cp = ptr; + size_t len = size; + size_t nfree, ncopy; + size_t written = 0; + size_t chunk; + + if (!len) return 0; + + while (len) { + if (chunks) { + if (offset == CachedFileChunkSize) { + it++; + if (it == (*chunks).end()) return written; + offset = 0; + } + chunk = *it; + } else { + offset = cachedFile->length % CachedFileChunkSize; + chunk = cachedFile->length / CachedFileChunkSize; + } + + if (chunk >= cachedFile->chunks->size()) { + cachedFile->chunks->resize(chunk + 1); + } + + nfree = CachedFileChunkSize - offset; + ncopy = (len >= nfree) ? nfree : len; + memcpy(&((*cachedFile->chunks)[chunk].data[offset]), cp, ncopy); + len -= ncopy; + cp += ncopy; + offset += ncopy; + written += ncopy; + + if (!chunks) { + cachedFile->length += ncopy; + } + + if (offset == CachedFileChunkSize) { + (*cachedFile->chunks)[chunk].state = CachedFile::chunkStateLoaded; + } + } + + if ((chunk == (cachedFile->length / CachedFileChunkSize)) && + (offset == (cachedFile->length % CachedFileChunkSize))) { + (*cachedFile->chunks)[chunk].state = CachedFile::chunkStateLoaded; + } + + return written; +} + +//------------------------------------------------------------------------ + |