1/* 2 * Copyright (C) 2006 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17// 18// Class providing access to a read-only asset. Asset objects are NOT 19// thread-safe, and should not be shared across threads. 20// 21#ifndef __LIBS_ASSET_H 22#define __LIBS_ASSET_H 23 24#include <stdio.h> 25#include <sys/types.h> 26#include "FileMap.h" 27#include "String8.h" 28#include "Errors.h" 29 30namespace android { 31 32/* 33 * Instances of this class provide read-only operations on a byte stream. 34 * 35 * Access may be optimized for streaming, random, or whole buffer modes. All 36 * operations are supported regardless of how the file was opened, but some 37 * things will be less efficient. [pass that in??] 38 * 39 * "Asset" is the base class for all types of assets. The classes below 40 * provide most of the implementation. The AssetManager uses one of the 41 * static "create" functions defined here to create a new instance. 42 */ 43class Asset { 44public: 45 virtual ~Asset(void); 46 47 static int32_t getGlobalCount(); 48 static String8 getAssetAllocations(); 49 50 /* used when opening an asset */ 51 typedef enum AccessMode { 52 ACCESS_UNKNOWN = 0, 53 54 /* read chunks, and seek forward and backward */ 55 ACCESS_RANDOM, 56 57 /* read sequentially, with an occasional forward seek */ 58 ACCESS_STREAMING, 59 60 /* caller plans to ask for a read-only buffer with all data */ 61 ACCESS_BUFFER, 62 } AccessMode; 63 64 enum { 65 /* data larger than this does not get uncompressed into a buffer */ 66#ifdef HAVE_ANDROID_OS 67 UNCOMPRESS_DATA_MAX = 1 * 1024 * 1024 68#else 69 UNCOMPRESS_DATA_MAX = 2 * 1024 * 1024 70#endif 71 }; 72 73 /* 74 * Read data from the current offset. Returns the actual number of 75 * bytes read, 0 on EOF, or -1 on error. 76 */ 77 virtual ssize_t read(void* buf, size_t count) = 0; 78 79 /* 80 * Seek to the specified offset. "whence" uses the same values as 81 * lseek/fseek. Returns the new position on success, or (off_t) -1 82 * on failure. 83 */ 84 virtual off_t seek(off_t offset, int whence) = 0; 85 86 /* 87 * Close the asset, freeing all associated resources. 88 */ 89 virtual void close(void) = 0; 90 91 /* 92 * Get a pointer to a buffer with the entire contents of the file. 93 */ 94 virtual const void* getBuffer(bool wordAligned) = 0; 95 96 /* 97 * Get the total amount of data that can be read. 98 */ 99 virtual off_t getLength(void) const = 0; 100 101 /* 102 * Get the total amount of data that can be read from the current position. 103 */ 104 virtual off_t getRemainingLength(void) const = 0; 105 106 /* 107 * Open a new file descriptor that can be used to read this asset. 108 * Returns -1 if you can not use the file descriptor (for example if the 109 * asset is compressed). 110 */ 111 virtual int openFileDescriptor(off_t* outStart, off_t* outLength) const = 0; 112 113 /* 114 * Return whether this asset's buffer is allocated in RAM (not mmapped). 115 * Note: not virtual so it is safe to call even when being destroyed. 116 */ 117 virtual bool isAllocated(void) const { return false; } 118 119 /* 120 * Get a string identifying the asset's source. This might be a full 121 * path, it might be a colon-separated list of identifiers. 122 * 123 * This is NOT intended to be used for anything except debug output. 124 * DO NOT try to parse this or use it to open a file. 125 */ 126 const char* getAssetSource(void) const { return mAssetSource.string(); } 127 128protected: 129 Asset(void); // constructor; only invoked indirectly 130 131 /* handle common seek() housekeeping */ 132 off_t handleSeek(off_t offset, int whence, off_t curPosn, off_t maxPosn); 133 134 /* set the asset source string */ 135 void setAssetSource(const String8& path) { mAssetSource = path; } 136 137 AccessMode getAccessMode(void) const { return mAccessMode; } 138 139private: 140 /* these operations are not implemented */ 141 Asset(const Asset& src); 142 Asset& operator=(const Asset& src); 143 144 /* AssetManager needs access to our "create" functions */ 145 friend class AssetManager; 146 147 /* 148 * Create the asset from a named file on disk. 149 */ 150 static Asset* createFromFile(const char* fileName, AccessMode mode); 151 152 /* 153 * Create the asset from a named, compressed file on disk (e.g. ".gz"). 154 */ 155 static Asset* createFromCompressedFile(const char* fileName, 156 AccessMode mode); 157 158#if 0 159 /* 160 * Create the asset from a segment of an open file. This will fail 161 * if "offset" and "length" don't fit within the bounds of the file. 162 * 163 * The asset takes ownership of the file descriptor. 164 */ 165 static Asset* createFromFileSegment(int fd, off_t offset, size_t length, 166 AccessMode mode); 167 168 /* 169 * Create from compressed data. "fd" should be seeked to the start of 170 * the compressed data. This could be inside a gzip file or part of a 171 * Zip archive. 172 * 173 * The asset takes ownership of the file descriptor. 174 * 175 * This may not verify the validity of the compressed data until first 176 * use. 177 */ 178 static Asset* createFromCompressedData(int fd, off_t offset, 179 int compressionMethod, size_t compressedLength, 180 size_t uncompressedLength, AccessMode mode); 181#endif 182 183 /* 184 * Create the asset from a memory-mapped file segment. 185 * 186 * The asset takes ownership of the FileMap. 187 */ 188 static Asset* createFromUncompressedMap(FileMap* dataMap, AccessMode mode); 189 190 /* 191 * Create the asset from a memory-mapped file segment with compressed 192 * data. "method" is a Zip archive compression method constant. 193 * 194 * The asset takes ownership of the FileMap. 195 */ 196 static Asset* createFromCompressedMap(FileMap* dataMap, int method, 197 size_t uncompressedLen, AccessMode mode); 198 199 200 /* 201 * Create from a reference-counted chunk of shared memory. 202 */ 203 // TODO 204 205 AccessMode mAccessMode; // how the asset was opened 206 String8 mAssetSource; // debug string 207 208 Asset* mNext; // linked list. 209 Asset* mPrev; 210}; 211 212 213/* 214 * =========================================================================== 215 * 216 * Innards follow. Do not use these classes directly. 217 */ 218 219/* 220 * An asset based on an uncompressed file on disk. It may encompass the 221 * entire file or just a piece of it. Access is through fread/fseek. 222 */ 223class _FileAsset : public Asset { 224public: 225 _FileAsset(void); 226 virtual ~_FileAsset(void); 227 228 /* 229 * Use a piece of an already-open file. 230 * 231 * On success, the object takes ownership of "fd". 232 */ 233 status_t openChunk(const char* fileName, int fd, off_t offset, size_t length); 234 235 /* 236 * Use a memory-mapped region. 237 * 238 * On success, the object takes ownership of "dataMap". 239 */ 240 status_t openChunk(FileMap* dataMap); 241 242 /* 243 * Standard Asset interfaces. 244 */ 245 virtual ssize_t read(void* buf, size_t count); 246 virtual off_t seek(off_t offset, int whence); 247 virtual void close(void); 248 virtual const void* getBuffer(bool wordAligned); 249 virtual off_t getLength(void) const { return mLength; } 250 virtual off_t getRemainingLength(void) const { return mLength-mOffset; } 251 virtual int openFileDescriptor(off_t* outStart, off_t* outLength) const; 252 virtual bool isAllocated(void) const { return mBuf != NULL; } 253 254private: 255 off_t mStart; // absolute file offset of start of chunk 256 off_t mLength; // length of the chunk 257 off_t mOffset; // current local offset, 0 == mStart 258 FILE* mFp; // for read/seek 259 char* mFileName; // for opening 260 261 /* 262 * To support getBuffer() we either need to read the entire thing into 263 * a buffer or memory-map it. For small files it's probably best to 264 * just read them in. 265 */ 266 enum { kReadVsMapThreshold = 4096 }; 267 268 FileMap* mMap; // for memory map 269 unsigned char* mBuf; // for read 270 271 const void* ensureAlignment(FileMap* map); 272}; 273 274 275/* 276 * An asset based on compressed data in a file. 277 */ 278class _CompressedAsset : public Asset { 279public: 280 _CompressedAsset(void); 281 virtual ~_CompressedAsset(void); 282 283 /* 284 * Use a piece of an already-open file. 285 * 286 * On success, the object takes ownership of "fd". 287 */ 288 status_t openChunk(int fd, off_t offset, int compressionMethod, 289 size_t uncompressedLen, size_t compressedLen); 290 291 /* 292 * Use a memory-mapped region. 293 * 294 * On success, the object takes ownership of "fd". 295 */ 296 status_t openChunk(FileMap* dataMap, int compressionMethod, 297 size_t uncompressedLen); 298 299 /* 300 * Standard Asset interfaces. 301 */ 302 virtual ssize_t read(void* buf, size_t count); 303 virtual off_t seek(off_t offset, int whence); 304 virtual void close(void); 305 virtual const void* getBuffer(bool wordAligned); 306 virtual off_t getLength(void) const { return mUncompressedLen; } 307 virtual off_t getRemainingLength(void) const { return mUncompressedLen-mOffset; } 308 virtual int openFileDescriptor(off_t* outStart, off_t* outLength) const { return -1; } 309 virtual bool isAllocated(void) const { return mBuf != NULL; } 310 311private: 312 off_t mStart; // offset to start of compressed data 313 off_t mCompressedLen; // length of the compressed data 314 off_t mUncompressedLen; // length of the uncompressed data 315 off_t mOffset; // current offset, 0 == start of uncomp data 316 317 FileMap* mMap; // for memory-mapped input 318 int mFd; // for file input 319 320 unsigned char* mBuf; // for getBuffer() 321}; 322 323// need: shared mmap version? 324 325}; // namespace android 326 327#endif // __LIBS_ASSET_H 328