1 /* 2 * Copyright (C) 2024 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16 #ifndef FRAMEWORKS_INNERKITSIMPL_ACCESSOR_INCLUDE_METADATA_STREAM_H 17 #define FRAMEWORKS_INNERKITSIMPL_ACCESSOR_INCLUDE_METADATA_STREAM_H 18 19 #include <cstddef> 20 #include <cstdint> 21 #include <fstream> 22 #include <string> 23 #include <vector> 24 25 #include "image_log.h" 26 #include "image_utils.h" 27 28 namespace OHOS { 29 namespace Media { 30 enum SeekPos { 31 BEGIN, 32 CURRENT, 33 END 34 }; 35 36 using byte = uint8_t; 37 38 constexpr int METADATA_STREAM_INVALID_FD = -1; 39 const std::string METADATA_STREAM_INVALID_PATH = ""; 40 41 enum class OpenMode { 42 Read, // Read mode 43 ReadWrite // Read-write mode 44 }; 45 46 /** 47 * Considering that the size of exif fields often exceeds 4K and is less than 32K, 48 * we set the increment of memory to 32K each time to minimize memory allocation. 49 */ 50 constexpr int METADATA_STREAM_PAGE_SIZE = 4096 * 8; 51 constexpr int METADATA_STREAM_ERROR_BUFFER_SIZE = 255; 52 53 /** 54 * Considering that the circuitry of solid-state storage is of a low-speed multi-concurrent form, 55 * we use a larger read/write buffer to activate the potential for concurrent read/write operations of the circuit, 56 * thereby increasing I/O throughput. 57 */ 58 constexpr int METADATA_STREAM_COPY_FROM_BUFFER_SIZE = 4096 * 32; 59 60 /** 61 * @class MetadataStream 62 * @brief A class for handling image streams. 63 * 64 * This class provides methods for reading from and seeking within an image stream. 65 * The maximum file size that can be handled depends on the system and compiler: 66 * - On a 32-bit system, the maximum file size is 2GB. 67 * - On a 64-bit system, the maximum file size depends on whether 'long' is compiled as 32-bit or 64-bit. 68 * If 'long' is 32-bit, the maximum file size is 2GB. 69 * If 'long' is 64-bit, the maximum file size is 8ZB (Zettabytes). 70 */ 71 class MetadataStream { 72 public: ~MetadataStream()73 virtual ~MetadataStream() {} 74 75 /* * 76 * Open the image stream with a specific mode. 77 * For FileMetadataStream, OpenMode::ReadWrite and OpenMode::Read have distinct behaviors. 78 * For BufferMetadataStream, only OpenMode::ReadWrite is applicable. If OpenMode::Read is 79 * passed, it will be ignored as there is no specific read-only mode implemented. 80 * @param mode The mode to open the image stream. 81 * @return true if it opens successfully, false otherwise. 82 */ 83 virtual bool Open(OpenMode mode = OpenMode::ReadWrite) = 0; 84 85 /* * 86 * Check if the image stream is open. 87 * For FileMetadataStream, this function is meaningful and checks if the file is open. 88 * For BufferMetadataStream, this function always returns true. 89 * @return true if it is open, false otherwise. 90 */ 91 virtual bool IsOpen() = 0; 92 93 /* * 94 * Flush the image stream. For FileMetadataStream, this function is used to clear the buffer and 95 * write the buffered data into the file. This operation ensures that all modifications are 96 * written to the file, so other FileMetadataStream objects opening the same file can see these 97 * modifications. For BufferMetadataStream, this function may not have a specific use as it might 98 * only operate data in memory and does not involve any file operations. However, it could still 99 * be used to trigger certain behaviors, such as notifying other objects that data has been 100 * modified, or releasing resources that are no longer needed. 101 * @return true if it flushes successfully, false otherwise 102 */ 103 virtual bool Flush() = 0; 104 105 /* * 106 * @brief Writes data to the image stream. 107 * @param data The data to be written. 108 * @param size The size of the data. The maximum size that can be written 109 * at once depends on the implementation. On 32-bit systems and above, 110 * a safe value is 2GB. 111 * @return The actual size of the data written. Returns -1 if an error 112 * occurred during writing. 113 */ 114 virtual ssize_t Write(byte *data, ssize_t size) = 0; 115 116 /* * 117 * Read data from the image stream 118 * @param buf The buffer to store the data read 119 * @param size The size of the data to be read 120 * @return The actual size of the data read, or -1 if an error occurred 121 */ 122 virtual ssize_t Read(byte *buf, ssize_t size) = 0; 123 124 /* * 125 * @brief Reads a byte from the image stream and moves the pointer to the next position. 126 * @return The byte read from the stream as a uint8_t. Returns -1 if an error occurred. 127 */ 128 virtual int ReadByte() = 0; 129 130 /* * 131 * Seek a specific position in the image stream 132 * @param offset The offset 133 * @param pos The starting position of the offset (from the head, current 134 * position, or tail) 135 * @return The new position. Returns -1 if an error occurred during seeking. 136 */ 137 virtual long Seek(long offset, SeekPos pos) = 0; 138 139 /* * 140 * Get the current position in the image stream 141 * @return The current position 142 */ 143 virtual long Tell() = 0; 144 145 /* * 146 * Check if the end of the image stream has been reached 147 * @return true if the end has been reached, false otherwise 148 */ 149 virtual bool IsEof() = 0; 150 151 /* * 152 * Create a memory map 153 * @param isWriteable If true, the created memory map will be writable; 154 * otherwise, the created memory map will be read-only. 155 * @return If the memory map is created successfully, return a pointer to 156 * the memory map; otherwise, return nullptr. 157 */ 158 virtual byte *GetAddr(bool isWriteable = false) = 0; 159 160 /* * 161 * Copy the entire content from the source MetadataStream to the current 162 * MetadataStream. After the copy operation, the current position of both the source 163 * MetadataStream and the current MetadataStream will be at their respective ends. 164 * @param src The source MetadataStream, this function will read data from this 165 * MetadataStream. 166 * @return true if the copy is successful, false otherwise. 167 */ 168 virtual bool CopyFrom(MetadataStream &src) = 0; 169 170 /* * 171 * Get the size of the MetadataStream 172 * @return The size of the MetadataStream 173 */ 174 virtual ssize_t GetSize() = 0; 175 176 /* * 177 * Get the size of the original file 178 * @return The size of the original file 179 */ GetOriginalSize()180 virtual size_t GetOriginalSize() 181 { 182 if (originalFd_ == METADATA_STREAM_INVALID_FD && originalPath_.empty()) { 183 return GetSize(); 184 } 185 186 size_t size = 0; 187 if (originalFd_ != METADATA_STREAM_INVALID_FD) { 188 ImageUtils::GetFileSize(originalFd_, size); 189 } else if (!originalPath_.empty()) { 190 ImageUtils::GetFileSize(originalPath_, size); 191 } 192 return size; 193 } 194 195 /* * 196 * Check if the original file has been changed 197 * @return true if the original file has been changed, false otherwise 198 */ IsFileChanged()199 virtual bool IsFileChanged() 200 { 201 if (isFileChanged_) { 202 return isFileChanged_; 203 } 204 if (GetOriginalSize() < static_cast<size_t>(GetSize())) { 205 IMAGE_LOGE("MetadataStream:: Original file has been changed"); 206 isFileChanged_ = true; 207 } 208 return isFileChanged_; 209 } 210 211 protected: 212 /* * 213 * Original file path 214 */ 215 std::string originalPath_ = METADATA_STREAM_INVALID_PATH; 216 217 /* * 218 * Original file fd number 219 */ 220 int originalFd_ = METADATA_STREAM_INVALID_FD; 221 222 /* * 223 * Whether original file is changed 224 */ 225 bool isFileChanged_ = false; 226 227 private: 228 /* * 229 * Close the image stream 230 */ 231 virtual void Close() = 0; 232 }; 233 } // namespace Media 234 } // namespace OHOS 235 #endif // FRAMEWORKS_INNERKITSIMPL_ACCESSOR_INCLUDE_METADATA_STREAM_H 236