1 // ================================================================================================= 2 // Copyright 2008 Adobe Systems Incorporated 3 // All Rights Reserved. 4 // 5 // NOTICE: Adobe permits you to use, modify, and distribute this file in accordance with the terms 6 // of the Adobe license agreement accompanying it. 7 // 8 // ================================================================================================= 9 10 #ifndef TagTree_H 11 #define TagTree_H 12 13 #include <map> 14 #include <list> 15 #include <string> 16 17 #include "source/EndianUtils.hpp" 18 #include "public/include/XMP_Const.h" //needed for setKV convenience functions 19 20 #include "samples/source/common/globals.h" 21 #include "samples/source/common/Log.h" 22 #include "samples/source/common/LargeFileAccess.hpp" 23 void LFA_Throw ( const char* msg, int id ); 24 25 using namespace std; 26 27 // TagTree routines must be able to throw these.. 28 class DumpFileException : public std::runtime_error { 29 public: 30 DumpFileException(const char* format, ...); 31 32 const char* what_dumpfile_reason(); //no override, but almost.. 33 private: 34 static const unsigned int DUMPFILE_MAX_ERROR_LENGTH=2048; 35 char buffer [DUMPFILE_MAX_ERROR_LENGTH+1]; 36 }; 37 38 class TagTree { 39 private: 40 struct Node; //forward-looking declaration 41 typedef std::list<Node> NodeList; 42 typedef std::list<Node>::iterator NodeListIter; 43 44 struct Node { 45 std::string key; // node structure name resp. tag name 46 std::string value; // value if applicable/of relevance 47 std::string comment; // comment string, add-on as many as you like 48 NodeList children; // children of this tag, if any 49 public: 50 //default-constructor is an std::container requirement. DO NOT ACTUALLY USE. NodeNode51 Node() { 52 key=std::string("unnamed"); // should be overridden at all times 53 value=std::string("no value"); 54 comment=std::string("no comment"); 55 children.clear(); // be safe (std::mac-issue..) clear beforehand 56 } 57 58 //the one to use NodeNode59 Node(std::string _key, std::string _value, std::string _comment) { 60 this->key = _key; 61 this->value = _value; 62 this->comment = _comment; 63 children.clear(); 64 } 65 }; 66 67 // the map (always alphabetic) to collect key-value pairs 68 // - Node* rather than string to have access to value and comment info 69 typedef std::map<std::string,Node*> TagMap; 70 TagMap tagMap; 71 72 //used for changeValue and addComment 73 //(NB: not null-ed or such on push+pop, thus stretches beyond) 74 Node* lastNode; 75 76 //we need a stack to iterate in and out 77 // during build-up and dump recursion 78 typedef std::list<Node*> NodeStack; 79 80 NodeStack nodeStack; 81 Node rootNode; //TODO: ("root",""); 82 83 // control verbosity to ease debugging: 84 static bool verbose; 85 86 public: 87 TagTree(); 88 ~TagTree(); 89 90 void reset(); 91 92 // verbosity control (mute by default ) =================================== 93 void setMute(); 94 void setVerbose(); 95 96 //input functions ========================================================= 97 98 void pushNode(const std::string key); 99 void pushNode(const char* format, ...); 100 101 // add file offset as comment -> own routine to better output 64 bit offsets... 102 void addOffset(LFA_FileRef file); 103 104 void popNode(); 105 void popAllNodes(); 106 107 //sets a key-value pair and optinal comment. value is also optional and may be set at a later time 108 //can also be used to set pure, standalone comments (using key==value=="") 109 void setKeyValue(const std::string key,const std::string value="", const std::string comment=""); 110 111 //updates the value of key without creating new key, value pairs. 112 void updateKeyValue ( const std::string key, const std::string value, const std::string comment = "" ); 113 114 // convenience functions ////////////////////////////////////////////////////////////////// 115 // these functions read bytes (assert in file-length), dump them to screen (as hex or as number) 116 // and optionally return the values for further processing 117 118 //read, convert endianess, dump certain values all in one go: 119 // * key - may be NULL if you just want to obtain the values but not make a KV entry 120 // * returnValue - returns the bytes digested 121 // * numOfBytes - 0-byte requests *are* legitimate, as they may reduce codeforks for the client 122 void digest(LFA_FileRef file,const std::string key="", 123 void* returnValue=NULL, 124 XMP_Int32 numOfBytes=0); 125 126 //////////////////////////////////////////////////////////////////////////////////// 127 // numeric digest routines 128 // 129 // same parameters as above, plus: 130 // * bigEndian - set to false, if the number is in the file as little endian 131 // ( correct return value according to machine type is taken care of for either setting) 132 // overload signed and unsigned, 32 and 16 bit 133 // Note, again: key may be NULL if you just want to obtain the values but not make a KV entry 134 XMP_Int64 digest64s(LFA_FileRef file,const std::string key="", bool BigEndian=false); 135 XMP_Uns64 digest64u(LFA_FileRef file,const std::string key="", bool BigEndian=false,bool hexDisplay=false); 136 XMP_Int32 digest32s(LFA_FileRef file,const std::string key="", bool BigEndian=false); 137 XMP_Uns32 digest32u(LFA_FileRef file,const std::string key="", bool BigEndian=false,bool hexDisplay=false); 138 XMP_Int16 digest16s(LFA_FileRef file,const std::string key="", bool BigEndian=false); 139 XMP_Uns16 digest16u(LFA_FileRef file,const std::string key="", bool BigEndian=false,bool hexDisplay=false); 140 141 // "expected" Overrides 142 void digest64s(XMP_Int64 expected, LFA_FileRef file,const std::string key="", bool BigEndian=false); 143 void digest64u(XMP_Uns64 expected, LFA_FileRef file,const std::string key="", bool BigEndian=false,bool hexDisplay=false); 144 void digest32s(XMP_Int32 expected, LFA_FileRef file,const std::string key="", bool BigEndian=false); 145 void digest32u(XMP_Uns32 expected, LFA_FileRef file,const std::string key="", bool BigEndian=false,bool hexDisplay=false); 146 void digest16s(XMP_Int16 expected, LFA_FileRef file,const std::string key="", bool BigEndian=false); 147 void digest16u(XMP_Uns16 expected, LFA_FileRef file,const std::string key="", bool BigEndian=false,bool hexDisplay=false); 148 149 //CBR Overrides 150 void digest64s(XMP_Int64* returnValue, LFA_FileRef file,const std::string key="", bool BigEndian=false); 151 void digest64u(XMP_Uns64* returnValue, LFA_FileRef file,const std::string key="", bool BigEndian=false,bool hexDisplay=false); 152 void digest32s(XMP_Int32* returnValue, LFA_FileRef file,const std::string key="", bool BigEndian=false); 153 void digest32u(XMP_Uns32* returnValue, LFA_FileRef file,const std::string key="", bool BigEndian=false,bool hexDisplay=false); 154 void digest16s(XMP_Int16* returnValue, LFA_FileRef file,const std::string key="", bool BigEndian=false); 155 void digest16u(XMP_Uns16* returnValue, LFA_FileRef file,const std::string key="", bool BigEndian=false,bool hexDisplay=false); 156 157 158 //8-bit string (whichever encoding -> "buginese") to std::string 159 //use length==0 to indicate zero-termination, 160 //otherwise indicated lenght will be grabbed also accross \0 's 161 //(length is counted w/o trailing zero termination, i.e. length("hans")==4 ) 162 // TODO: length default = 0 not yet implemented 163 // verifyZeroTerm 164 // - has an effect only if a length!=0 is given (otherwise things go up to the 0 anyway) 165 // - in this case, asserts that the string has a terminating zero 166 // (_after_ <length> bytes, otherwise that byte is not read which has an impact on the filepointer!) 167 // would throw if any zero (\0) is encountered prior to that 168 std::string digestString(LFA_FileRef file,const std::string key="", size_t length=0, bool verifyZeroTerm=false, bool allowEarlyZeroTerm=false ); 169 170 // (wrappers) 171 // standalone comment 172 void comment(const std::string comment); 173 // standalone comment 174 // be aware of bug1741056, feeding 64bit numbers might not output correctly 175 void comment(const char* format, ...); 176 177 //sometimes its worth changing (or actually setting for the first time) they current 178 //(aka last set) key/value at a later time. includes correction in tagmap. 179 void changeValue(const std::string value); 180 void changeValue(const char* format, ...); 181 182 //adds a comment to last prior entry ( which could be KeyValue, Node or standalone comment...) 183 void addComment(const std::string comment); 184 //adds a comment to last prior entry ( which could be KeyValue, Node or standalone comment...) 185 void addComment(const char* format, ...); 186 187 //output functions =========================================================== 188 void dumpTree(bool commentsFlag=true, Node* pNode = NULL,unsigned int depth=0); 189 190 void dumpTagMap(); 191 void dumpTagList(Node* pNode = NULL,unsigned int depth=0); 192 193 std::string getValue(const std::string key); 194 std::string getComment(const std::string key); 195 unsigned int getSubNodePos( const std::string nodeKey, const std::string parentKey = "", int skip = 0 ); 196 XMP_Int64 getNodeSize( const std::string nodeKey ); 197 198 //returns true if there is such a node, false if not, error if it happens to be key-value pair 199 bool hasNode(const std::string key); 200 XMP_Int32 getNodeCount(const std::string key); 201 }; 202 203 #endif 204