[go: up one dir, main page]

File: exceptionmanager.cpp

package info (click to toggle)
qgit 2.10-2
  • links: PTS, VCS
  • area: main
  • in suites: bookworm, trixie
  • size: 1,424 kB
  • sloc: cpp: 13,042; xml: 25; sh: 25; javascript: 16; makefile: 3
file content (180 lines) | stat: -rw-r--r-- 4,911 bytes parent folder | download | duplicates (8)
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
/*
	Description: Support for recursive C++ exception handling
			compatible with Qt qApp->processEvents()

			See exception_manager.txt for details.

	Author: Marco Costalba (C) 2005-2007

	Copyright: See COPYING file that comes with this distribution

*/
#include <QList>
#include "exceptionmanager.h"

ExceptionManager::ExceptionManager() {

	excpId = regionId = currentRegionId = 1;
	descriptions.append("we start from 1");
}

void ExceptionManager::init(int* excp, const QString& desc) {

	*excp = excpId++;
	descriptions.append(desc);
}

const QString ExceptionManager::desc(int excpId) {

	return descriptions[excpId];
}

bool ExceptionManager::isMatch(int value, int excp, const QString& context) {

	bool match = (value == excp);
	if (match) {
		QString info("Caught exception \'" + descriptions[excp] +
		             "\' while in " + context);
		qDebug("%s", info.toLatin1().constData());
	}
	return match;
}

void ExceptionManager::add(int excpId, bool verbose) {
// add a new exception in currentThrowableSet

	// are prepended so to use a for loop starting
	// from begin to find the latest. Exceptions are
	// always added/removed from both totalThrowableSet
	// and regionThrowableSet
	totalThrowableSet.prepend(Exception(excpId, verbose));
	regionThrowableSet.prepend(Exception(excpId, verbose));
}

void ExceptionManager::remove(int excpId) {
// removes ONE exception in totalThrowableSet and ONE in regionThrowableSet.
// if add and remove calls are correctly nested the removed
// excp should be the first in both throwable sets

	if (totalThrowableSet.isEmpty() || regionThrowableSet.isEmpty()) {
		qDebug("ASSERT in remove: removing %i from an empty set", excpId);
		return;
	}
	// remove from region.
	SetIt itReg(regionThrowableSet.begin());
	if ((*itReg).excpId != excpId) {
		qDebug("ASSERT in remove: %i is not the first in list", excpId);
		return;
	}
	regionThrowableSet.erase(itReg);

	// remove from total.
	SetIt itTot(totalThrowableSet.begin());
	if ((*itTot).excpId != excpId) {
		qDebug("ASSERT in remove: %i is not the first in list", excpId);
		return;
	}
	totalThrowableSet.erase(itTot);
}

ExceptionManager::SetIt ExceptionManager::findExcp(ThrowableSet& ts,
		const SetIt& startIt, int excpId) {

	SetIt it(startIt);
	for ( ; it != ts.end(); ++it)
		if ((*it).excpId == excpId)
			break;
	return it;
}

void ExceptionManager::setRaisedFlag(ThrowableSet& ts, int excpId) {

	SetIt it(findExcp(ts, ts.begin(), excpId));
	while (it != ts.end()) {
		(*it).isRaised = true;
		it = findExcp(ts, ++it, excpId);
	}
}

void ExceptionManager::raise(int excpId) {

	if (totalThrowableSet.isEmpty())
		return;

	// check totalThrowableSet to find if excpId is throwable
	SetIt it = findExcp(totalThrowableSet, totalThrowableSet.begin(), excpId);
	if (it == totalThrowableSet.end())
		return;

	// we have found an exception. Set raised flag in regionThrowableSet
	setRaisedFlag(regionThrowableSet, excpId);

	// then set the flag in all regions throwableSetList
	QMap<int, ThrowableSet>::iterator itList(throwableSetMap.begin());
	while (itList != throwableSetMap.end()) {
		setRaisedFlag(*itList, excpId);
		++itList;
	}
}

int ExceptionManager::saveThrowableSet() {
// here we save regionThrowableSet _and_ update the region.
// regionThrowableSet is saved with the current region index.
// then current region is changed to a new and never used index

	int oldCurrentRegionId = currentRegionId;
	throwableSetMap.insert(currentRegionId, regionThrowableSet);
	currentRegionId = ++regionId;

	// we use this call to trigger a region boundary crossing
	// so we have to clear the new region throwables. We still
	// have totalThrowableSet to catch any request.
	regionThrowableSet.clear();

	return oldCurrentRegionId;
}

void ExceptionManager::restoreThrowableSet(int regionId) {

	if (!throwableSetMap.contains(regionId)) {
		qDebug("ASSERT in restoreThrowableSet: region %i not found", regionId);
		return;
	}
	regionThrowableSet = throwableSetMap[regionId];
	throwableSetMap.remove(regionId);
}

bool ExceptionManager::isPending(int excpId) {

	// check in ALL regions if an exception request is pending
	QMap<int, ThrowableSet>::const_iterator itList(throwableSetMap.constBegin());
	while (itList != throwableSetMap.constEnd()) {

		ThrowableSet::const_iterator it((*itList).constBegin());
		for ( ; it != (*itList).constEnd(); ++it)
			if ((*it).isRaised && (*it).excpId == excpId)
				return true;
		++itList;
	}
	return false;
}

void ExceptionManager::throwPending() {

	if (regionThrowableSet.isEmpty())
		return;

	ThrowableSet::const_iterator it(regionThrowableSet.constBegin());
	for ( ; it != regionThrowableSet.constEnd(); ++it)
		if ((*it).isRaised)
			break;

	if (it == regionThrowableSet.constEnd())
		return;

	int excpToThrow = (*it).excpId;
	if ((*it).verbose)
		qDebug("Thrown exception \'%s\'", desc(excpToThrow).toLatin1().constData());

	throw excpToThrow;
}