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