1 // ================================================================================================= 2 // ADOBE SYSTEMS INCORPORATED 3 // Copyright 2010 Adobe Systems Incorporated 4 // All Rights Reserved 5 // 6 // NOTICE: Adobe permits you to use, modify, and distribute this file in accordance with the terms 7 // of the Adobe license agreement accompanying it. 8 // ================================================================================================= 9 10 #ifndef _IChunkBehavior_h_ 11 #define _IChunkBehavior_h_ 12 13 #include "public/include/XMP_Environment.h" // ! This must be the first include. 14 #include "public/include/XMP_Const.h" 15 #include "public/include/XMP_IO.hpp" 16 #include <vector> 17 18 namespace IFF_RIFF 19 { 20 21 /** 22 The IChunkBehavior is an interface that provides access to algorithm 23 for the read and write process of IFF/RIFF formated streams. 24 A file format specific instance based on this interface gets injected into 25 the class ChunkController and offers format specific algorithm wherever 26 the processing of a certain file format differs from the general specification 27 of RIFF/IFF. 28 That is e.g. the RF64 format where it is possible that the size value of the 29 top level chunk doesn't represent the real size. Or AVI, where are special rules 30 if the size of a chunk exceed the 4GB border. 31 */ 32 33 class IChunkContainer; 34 class Chunk; 35 struct ChunkIdentifier; 36 class ChunkPath; 37 38 class IChunkBehavior 39 { 40 public: IChunkBehavior()41 IChunkBehavior() : mMovablePaths(NULL) {} ~IChunkBehavior()42 virtual ~IChunkBehavior() {}; 43 44 /** 45 * Set list of chunk paths of chunks that might be moved within the hierarchy 46 */ setMovablePaths(std::vector<ChunkPath> * paths)47 inline void setMovablePaths( std::vector<ChunkPath>* paths ) { mMovablePaths = paths; } 48 49 /** 50 Validate the passed in size value, identify the valid size if the passed in isn't valid 51 and return the valid size. 52 throw an exception if the passed in size isn't valid and there's no way to identify a 53 valid size. 54 55 @param size Size value 56 @param id Identifier of chunk 57 @param tree Chunk tree 58 @param stream Stream handle 59 60 @return Valid size value. 61 */ 62 virtual XMP_Uns64 getRealSize( const XMP_Uns64 size, const ChunkIdentifier& id, IChunkContainer& tree, XMP_IO* stream ) = 0; 63 64 /** 65 Return the maximum size of a single chunk, i.e. the maximum size of a top-level chunk. 66 67 @return Maximum size 68 */ 69 virtual XMP_Uns64 getMaxChunkSize() const = 0; 70 71 /** 72 Return true if the passed identifier is valid for top-level chunks of a certain format. 73 74 @param id Chunk identifier 75 @param chunkNo order number of top-level chunk 76 @return true, if passed id is a valid top-level chunk 77 */ 78 virtual bool isValidTopLevelChunk( const ChunkIdentifier& id, XMP_Uns32 chunkNo ) = 0; 79 80 /** 81 Fix the hierarchy of chunks depending ones based on size changes of one or more chunks 82 and second based on format specific rules. 83 Throw an exception if the hierarchy can't be fixed. 84 85 @param tree Vector of root chunks. 86 */ 87 virtual void fixHierarchy( IChunkContainer& tree ) = 0; 88 89 /** 90 Insert a new chunk into the hierarchy of chunks. The behavior needs to decide the position 91 of the new chunk and has to do the insertion. 92 93 @param tree Chunk tree 94 @param chunk New chunk 95 */ 96 virtual void insertChunk( IChunkContainer& tree, Chunk& chunk ) = 0; 97 98 /** 99 Remove the chunk described by the passed ChunkPath. 100 101 @param tree Chunk tree 102 @param path Path to the chunk that needs to be removed 103 104 @return true if the chunk was removed and need to be deleted 105 */ 106 virtual bool removeChunk( IChunkContainer& tree, Chunk& chunk ) = 0; 107 108 protected: 109 /** 110 Create a FREE chunk. 111 If the chunkSize is smaller than the header+type - size then create an annotation chunk. 112 If the passed size is odd, then add a pad byte. 113 114 @param chunkSize Total size including header 115 @return New FREE chunk 116 */ 117 virtual Chunk* createFREE( XMP_Uns64 chunkSize ) = 0; 118 119 /** 120 Check if the passed chunk is a FREE chunk. 121 (Could be also a small annotation chunk with zero bytes in its data) 122 123 @param chunk A chunk 124 125 @return true if the passed chunk is a FREE chunk 126 */ 127 virtual XMP_Bool isFREEChunk( const Chunk& chunk ) const = 0; 128 129 /** 130 Return the minimum size of a FREE chunk 131 */ 132 virtual XMP_Uns64 getMinFREESize( ) const 133 = 0; 134 protected: 135 /************************************************************************/ 136 /* END of Interface. The following are helper functions for all derived */ 137 /* Behavior Classes */ 138 /************************************************************************/ 139 140 /** 141 Find a FREE chunk with the passed total size (including header). If the FREE chunk is found then 142 take care of the fact that is has to be that large (or larger) then the minimum size of a FREE chunk. 143 The method takes also into account that the passed size probably not includes a pad byte 144 145 @param tree Parent tree 146 @param requiredSize Required total size (including header) 147 148 @return Index of found FREE chunk 149 */ 150 XMP_Int32 findFREEChunk( const IChunkContainer& tree, XMP_Uns64 requiredSize ); 151 152 /** 153 May we move a chunk of passed id/type 154 155 @param identifier id and type of chunk 156 @return true if such a chunk might be moved within the tree 157 */ 158 bool isMovable( const Chunk& chunk ) const; 159 160 /** 161 Validate recursively the offset values of all chunks. 162 Throws an exception if there is any discrepancy with the calculated offset. 163 164 @param tree (Sub-)tree of chunks 165 @param startOffset First offset in the (sub-)tree 166 */ 167 void validateOffsets( IChunkContainer& tree, XMP_Uns64 startOffset = 0 ); 168 169 /** 170 Retrieve the free space at the passed position in the child list of the parent tree. 171 If there's a FREE chunk then return it. 172 173 @param outFreeBytes On return it takes the number of free bytes 174 @param tree Parent tree 175 @param index Position in the child list of the parent tree 176 177 @return FREE chunk if available 178 */ 179 Chunk* getFreeSpace( XMP_Int64& outFreeBytes, const IChunkContainer& tree, XMP_Uns32 index ) const ; 180 181 /** 182 Try to arrange all chunks of the source tree at their current location. 183 The method looks for FREE chunk around or for size changes of the chunks around and try that space. 184 If a chunk can't be arrange at its location it is moved to the end of the destination tree. 185 186 @param srcTree Tree that consists of the chunks that needs to be arranged 187 @param destTree Tree where chunks are added to if they can't be arranged 188 189 @return Index of last proceeded chunk 190 */ 191 void arrangeChunksInPlace( IChunkContainer& srcTree, IChunkContainer& destTree ); 192 193 /** 194 This method proceeds the list of Chunks of the source tree in the passed range and looks for FREE chunks 195 in the destination tree to move the source chunks to. 196 Source tree and destination tree could be one and the same but it's not required. If both trees are the 197 same then it's not allowed to cross source and destination ranges. 198 199 @param srcTree Tree that consists of the chunks that needs to be arranged 200 @param destTree Tree where the method looks for FREE chunks 201 @param srcStart Start index within the source tree 202 @param srcEnd End index within the source tree (if booth, srcStart and srcEnd are zero then the complete list 203 of the source tree is proceeded) 204 @param destStart Start index within the destination tree 205 @param destEnd End index within the destination tree (if booth, destStart and destEnd are zero then the complete list 206 of the destination tree is proceeded) 207 */ 208 void arrangeChunksInTree( IChunkContainer& srcTree, IChunkContainer& destTree ); 209 210 /** 211 Try to merge existing FREE chunks at the passed position in the child list 212 of the passed parent tree. 213 The algorithm looks at the position, before the position and after the position. 214 215 @param tree Parent tree 216 @param index Position in the child list of the parent tree 217 218 @return FREE chunk if available at the passed position (in case of a merge 219 the merged FREE chunk) 220 */ 221 Chunk* mergeFreeChunks( IChunkContainer& tree, XMP_Uns32 index ); 222 223 /** 224 Move a range of chunks from one container to another starting at the start index up to the 225 end of the srcTree. 226 227 @param srcTree Source container 228 @param destTree Destination container 229 @param start Start index of source container 230 */ 231 void moveChunks( IChunkContainer& srcTree, IChunkContainer& destTree, XMP_Uns32 start ); 232 233 private: 234 std::vector<ChunkPath>* mMovablePaths; 235 }; 236 237 } // IChunkBehavior 238 239 #endif 240