File: TagTree.h

package info (click to toggle)
exempi 2.2.0-1
  • links: PTS, VCS
  • area: main
  • in suites: wheezy
  • size: 9,276 kB
  • sloc: cpp: 49,877; sh: 10,986; makefile: 272; ansic: 93
file content (198 lines) | stat: -rw-r--r-- 8,671 bytes parent folder | download | duplicates (2)
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