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