Project

General

Profile

Statistics
| Branch: | Revision:

root / src / envir / objectprinter.cc @ 7c7d95e5

History | View | Annotate | Download (9.84 KB)

1 01873262 Georg Kunz
//==========================================================================
2
//  OBJECTPRINTER.CC - part of
3
//                     OMNeT++/OMNEST
4
//            Discrete System Simulation in C++
5
//
6
//  Author: Levente Meszaros
7
//
8
//==========================================================================
9
10
/*--------------------------------------------------------------*
11
  Copyright (C) 1992-2008 Andras Varga
12
  Copyright (C) 2006-2008 OpenSim Ltd.
13

14
  This file is distributed WITHOUT ANY WARRANTY. See the file
15
  `license' for details on this and other legal matters.
16
*--------------------------------------------------------------*/
17
18
#include "stringutil.h"
19
#include "cconfiguration.h"
20
#include "carray.h"
21
#include "cmodule.h"
22
#include "cgate.h"
23
#include "cclassdescriptor.h"
24
#include "commonutil.h"
25
#include "stringtokenizer.h"
26
#include "matchexpression.h"
27
#include "matchablefield.h"
28
#include "matchableobject.h"
29
#include "objectprinter.h"
30
31
USING_NAMESPACE
32
33
#define MAXIMUM_OBJECT_PRINTER_LEVEL 20
34
35
static ObjectPrinterRecursionControl defaultRecurseIntoMessageFields(void *object, cClassDescriptor *descriptor, int fieldIndex, void *fieldValue, void **parents, int level) {
36
    const char *fieldName = descriptor->getFieldName(object, fieldIndex);
37
    return strcmp(fieldName, "owner") ? RECURSE : SKIP;
38
}
39
40
ObjectPrinter::ObjectPrinter(ObjectPrinterRecursionPredicate recursionPredicate,
41
                             const std::vector<MatchExpression*>& objectMatchExpressions,
42
                             const std::vector<std::vector<MatchExpression*> >& fieldNameMatchExpressionsList,
43
                             int indentSize)
44
{
45
    Assert(objectMatchExpressions.size() == fieldNameMatchExpressionsList.size());
46
    this->recursionPredicate = recursionPredicate ? recursionPredicate : defaultRecurseIntoMessageFields;
47
    this->objectMatchExpressions = objectMatchExpressions;
48
    this->fieldNameMatchExpressionsList = fieldNameMatchExpressionsList;
49
    this->indentSize = indentSize;
50
}
51
52
ObjectPrinter::ObjectPrinter(ObjectPrinterRecursionPredicate recursionPredicate, const char *objectFieldMatcherPattern, int indentSize)
53
{
54
    std::vector<MatchExpression*> objectMatchExpressions;
55
    std::vector<std::vector<MatchExpression*> > fieldNameMatchExpressionsList;
56
57
    StringTokenizer tokenizer(objectFieldMatcherPattern, "|"); // TODO: use ; when it does not mean comment anymore
58
    std::vector<std::string> patterns = tokenizer.asVector();
59
60
    for (int i = 0; i < (int)patterns.size(); i++) {
61
        char *objectPattern = (char *)patterns[i].c_str();
62
        char *fieldNamePattern = strchr(objectPattern, ':');
63
64
        if (fieldNamePattern) {
65
            *fieldNamePattern = '\0';
66
            StringTokenizer fieldNameTokenizer(fieldNamePattern + 1, ",");
67
            std::vector<std::string> fieldNamePatterns = fieldNameTokenizer.asVector();
68
            std::vector<MatchExpression*> fieldNameMatchExpressions;
69
70
            for (int j = 0; j < (int)fieldNamePatterns.size(); j++)
71
                fieldNameMatchExpressions.push_back(new MatchExpression(fieldNamePatterns[j].c_str(), false, true, true));
72
73
            fieldNameMatchExpressionsList.push_back(fieldNameMatchExpressions);
74
        }
75
        else {
76
            std::vector<MatchExpression*> fieldNameMatchExpressions;
77
            fieldNameMatchExpressions.push_back(new MatchExpression("*", false, true, true));
78
            fieldNameMatchExpressionsList.push_back(fieldNameMatchExpressions);
79
        }
80
81
        objectMatchExpressions.push_back(new MatchExpression(objectPattern, false, true, true));
82
    }
83
84
    Assert(objectMatchExpressions.size() == fieldNameMatchExpressionsList.size());
85
    this->recursionPredicate = recursionPredicate ? recursionPredicate : defaultRecurseIntoMessageFields;
86
    this->objectMatchExpressions = objectMatchExpressions;
87
    this->fieldNameMatchExpressionsList = fieldNameMatchExpressionsList;
88
    this->indentSize = indentSize;
89
}
90
91
ObjectPrinter::~ObjectPrinter()
92
{
93
    for (int i = 0; i < (int)objectMatchExpressions.size(); i++) {
94
        delete objectMatchExpressions[i];
95
        std::vector<MatchExpression*>& fieldNameMatchExpressions = fieldNameMatchExpressionsList[i];
96
        for (int j = 0; j < (int)fieldNameMatchExpressions.size(); j++)
97
            delete fieldNameMatchExpressions[j];
98
    }
99
100
}
101
102
void ObjectPrinter::printObjectToStream(std::ostream& ostream, cObject *object)
103
{
104
    void *parents[MAXIMUM_OBJECT_PRINTER_LEVEL];
105
    cClassDescriptor *descriptor = cClassDescriptor::getDescriptorFor(object);
106
    ostream << "class " << descriptor->getName() << " {\n";
107
    printObjectToStream(ostream, object, descriptor, parents, 0);
108
    ostream << "}\n";
109
}
110
111
std::string ObjectPrinter::printObjectToString(cObject *object)
112
{
113
    std::stringstream out;
114
    printObjectToStream(out, object);
115
    return out.str();
116
}
117
118
void ObjectPrinter::printObjectToStream(std::ostream& ostream, void *object, cClassDescriptor *descriptor, void **parents, int level)
119
{
120
    if (level == MAXIMUM_OBJECT_PRINTER_LEVEL) {
121
        printIndent(ostream, level);
122
        ostream << "<pruned>\n";
123
        return;
124
    }
125
    else {
126
        for (int i = 0; i < level; i++) {
127
            if (parents[i] == object) {
128
                printIndent(ostream, level);
129
                ostream << "<recursion>\n";
130
                return;
131
            }
132
        }
133
    }
134
    if (!descriptor) {
135
        printIndent(ostream, level);
136
        if (level == 0)
137
            ostream << "{...}\n";
138
        else
139
            ostream << "...\n";
140
    }
141
    else {
142
        parents[level] = object;
143
        for (int fieldIndex = 0; fieldIndex < descriptor->getFieldCount(object); fieldIndex++) {
144
            bool isArray = descriptor->getFieldIsArray(object, fieldIndex);
145
            bool isPointer = descriptor->getFieldIsPointer(object, fieldIndex);
146
            bool isCompound = descriptor->getFieldIsCompound(object, fieldIndex);
147
            bool isCObject = descriptor->getFieldIsCObject(object, fieldIndex);
148
            const char *fieldType = descriptor->getFieldTypeString(object, fieldIndex);
149
            const char *fieldName = descriptor->getFieldName(object, fieldIndex);
150
151
            int size = isArray ? descriptor->getArraySize(object, fieldIndex) : 1;
152
            for (int elementIndex = 0; elementIndex < size; elementIndex++) {
153
                void *fieldValue = isCompound ? descriptor->getFieldStructPointer(object, fieldIndex, elementIndex) : NULL;
154
155
                ObjectPrinterRecursionControl result = RECURSE;
156
                if (recursionPredicate)
157
                    result = recursionPredicate(object, descriptor, fieldIndex, fieldValue, parents, level);
158
                if (result == SKIP || (descriptor->extendsCObject() && !matchesObjectField((cObject *)object, fieldIndex)))
159
                    continue;
160
161
                printIndent(ostream, level + 1);
162
                ostream << fieldType << " ";
163
164
                if (isPointer)
165
                    ostream << "*";
166
                ostream << fieldName;
167
168
                if (isArray)
169
                    ostream << "[" << elementIndex << "]";
170
                ostream << " = ";
171
172
                if (isCompound) {
173
                    if (fieldValue) {
174
                        cClassDescriptor *fieldDescriptor = isCObject ? cClassDescriptor::getDescriptorFor((cObject *)fieldValue) :
175
                                                                        cClassDescriptor::getDescriptorFor(descriptor->getFieldStructName(object, fieldIndex));
176
177
                        if (isCObject && result == FULL_NAME)
178
                            ostream << ((cObject *)fieldValue)->getFullName() << "\n";
179
                        else if (isCObject && result == FULL_PATH)
180
                            ostream << ((cObject *)fieldValue)->getFullPath() << "\n";
181
                        else if (fieldDescriptor) {
182
                            if (isCObject)
183
                                ostream << "class " << ((cObject *)fieldValue)->getClassName() << " ";
184
                            else
185
                                ostream << "struct " << descriptor->getFieldStructName(object, fieldIndex) << " ";
186
187
                            ostream << "{\n";
188
                            printObjectToStream(ostream, fieldValue, fieldDescriptor, parents, level + 1);
189
                            printIndent(ostream, level + 1);
190
                            ostream << "}\n";
191
                        }
192
                        else {
193
                            std::string value = descriptor->getFieldAsString(object, fieldIndex, elementIndex);
194
                            ostream << QUOTE(value.c_str()) << "\n";
195
                        }
196
                    }
197
                    else
198
                        ostream << "NULL\n";
199
                }
200
                else {
201
                    std::string value = descriptor->getFieldAsString(object, fieldIndex, elementIndex);
202
                    ostream << QUOTE(value.c_str()) << "\n";
203
                }
204
            }
205
        }
206
    }
207
}
208
209
void ObjectPrinter::printIndent(std::ostream& ostream, int level)
210
{
211
    int count = level * indentSize;
212
    for (int i = 0; i < count; i++)
213
        ostream << " ";
214
}
215
216
bool ObjectPrinter::matchesObjectField(cObject *object, int fieldIndex)
217
{
218
    const MatchableObjectAdapter matchableObject(MatchableObjectAdapter::CLASSNAME, object);
219
220
    for (int i = 0; i < (int)objectMatchExpressions.size(); i++) {
221
        MatchExpression *objectMatchExpression = objectMatchExpressions[i];
222
223
        if (objectMatchExpression->matches(&matchableObject)) {
224
            std::vector<MatchExpression*>& fieldNameMatchExpressions = fieldNameMatchExpressionsList[i];
225
226
            for (int j = 0; j < (int)fieldNameMatchExpressions.size(); j++) {
227
                MatchExpression *fieldNameMatchExpression = fieldNameMatchExpressions[j];
228
                const MatchableFieldAdapter matchableField(object, fieldIndex);
229
230
                if (fieldNameMatchExpression->matches(&matchableField))
231
                    return true;
232
            }
233
        }
234
    }
235
236
    return false;
237
}