Project

General

Profile

Statistics
| Branch: | Revision:

root / src / nedxml / neddtdvalidatorbase.cc @ 68da4f12

History | View | Annotate | Download (6.4 KB)

1
//==========================================================================
2
// neddtdvalidatorbase.cc -
3
//
4
//                     OMNeT++/OMNEST
5
//            Discrete System Simulation in C++
6
//
7
//==========================================================================
8

    
9
/*--------------------------------------------------------------*
10
  Copyright (C) 2002-2008 Andras Varga
11
  Copyright (C) 2006-2008 OpenSim Ltd.
12

13
  This file is distributed WITHOUT ANY WARRANTY. See the file
14
  `license' for details on this and other legal matters.
15
*--------------------------------------------------------------*/
16

    
17
#include <string.h>
18
#include <stdio.h>
19
#include <assert.h>
20
#include "opp_ctype.h"
21
#include "nederror.h"
22
#include "neddtdvalidatorbase.h"
23

    
24
USING_NAMESPACE
25

    
26

    
27
void NEDDTDValidatorBase::checkSequence(NEDElement *node, int tags[], char mult[])
28
{
29
    NEDElement *p = node->getFirstChild();
30
    for (int i=0; tags[i]; i++)
31
    {
32
       switch (mult[i])
33
       {
34
         case '1':
35
           if (!p || p->getTagCode()!=tags[i])
36
               {errors->addError(node,"DTD validation error: child element '%s' unexpected", (p?p->getTagName():"")); return;}
37
           p = p->getNextSibling();
38
           break;
39
         case '?':
40
           if (p && p->getTagCode()==tags[i])
41
               p = p->getNextSibling();
42
           break;
43
         case '+':
44
           if (!p || p->getTagCode()!=tags[i])
45
               {errors->addError(node, "DTD validation error: child element '%s' unexpected", (p?p->getTagName():"")); return;}
46
           p = p->getNextSibling();
47
           while (p && p->getTagCode()==tags[i])
48
               p = p->getNextSibling();
49
           break;
50
         case '*':
51
           while (p && p->getTagCode()==tags[i])
52
               p = p->getNextSibling();
53
           break;
54
       }
55
    }
56
    if (p)
57
        errors->addError(node, "DTD validation error: child element '%s' unexpected", p->getTagName());
58
}
59

    
60
static int isInVector(int a, int v[])
61
{
62
    for (int i=0; v[i]; i++)  // v[] is zero-terminated
63
        if (v[i]==a)
64
            return true;
65
    return false;
66
}
67

    
68
void NEDDTDValidatorBase::tryCheckChoice(NEDElement *node, NEDElement *&curchild, int tags[], char mult)
69
{
70
    // note: 'node' argument is solely used by errors->addError() (when curchild==NULL)
71
    if (mult=='?')
72
    {
73
        // skip optional matching element
74
        if (curchild && isInVector(curchild->getTagCode(), tags))
75
            curchild = curchild->getNextSibling();
76
    }
77
    else if (mult=='1' || mult=='+')
78
    {
79
        // match and skip first element of "1" or "+" sequence
80
        if (!curchild || !isInVector(curchild->getTagCode(), tags))
81
            {errors->addError(node,"DTD validation error: child element of multiplicity '1' or '+' missing"); return;}
82
        curchild = curchild->getNextSibling();
83
    }
84

    
85
    if (mult=='+' || mult=='*')
86
    {
87
        // skip potential further elements of "+" or "*" sequence
88
        while (curchild && isInVector(curchild->getTagCode(), tags))
89
            curchild = curchild->getNextSibling();
90
    }
91
}
92

    
93
void NEDDTDValidatorBase::checkChoice(NEDElement *node, int tags[], char mult)
94
{
95
    NEDElement *curchild = node->getFirstChild();
96
    tryCheckChoice(node, curchild, tags, mult);
97
    if (curchild)
98
        errors->addError(node,"DTD validation error: child element '%s' unexpected", curchild->getTagName());
99
}
100

    
101
void NEDDTDValidatorBase::checkSeqOfChoices(NEDElement *node, Choice choices[], int n)
102
{
103
    NEDElement *curchild = node->getFirstChild();
104
    for (int i=0; i<n; i++)
105
        tryCheckChoice(node, curchild, choices[i].tags, choices[i].mult);
106
    if (curchild)
107
        errors->addError(node,"DTD validation error: child element '%s' unexpected", curchild->getTagName());
108
}
109

    
110
void NEDDTDValidatorBase::checkEmpty(NEDElement *node)
111
{
112
    if (node->getFirstChild())
113
        errors->addError(node,"DTD validation error: EMPTY element has children\n");
114
}
115

    
116
void NEDDTDValidatorBase::checkRequiredAttribute(NEDElement *node, const char *attr)
117
{
118
    const char *s = node->getAttribute(attr);
119
    assert(s);
120
    if (!*s)
121
        errors->addError(node,"DTD validation error: required attribute '%s' is empty", attr);
122
}
123

    
124
void NEDDTDValidatorBase::checkEnumeratedAttribute(NEDElement *node, const char *attr, const char *vals[], int n)
125
{
126
    const char *s = node->getAttribute(attr);
127
    assert(s);
128
    for (int i=0; i<n; i++)
129
        if (!strcmp(s, vals[i]))
130
            return;
131
    if (n==0)
132
        INTERNAL_ERROR1(node,"no allowed values for enumerated attribute '%s'", attr);
133
    errors->addError(node,"DTD validation error: invalid value '%s' for attribute '%s', not one of the "
134
                     "enumerated values ('%s',...)", s, attr, vals[0]);
135
}
136

    
137
void NEDDTDValidatorBase::checkNameAttribute(NEDElement *node, const char *attr)
138
{
139
    //
140
    // NOTE: we use this method for validating NMTOKEN attributes in our DTD.
141
    // In our NED DTD we use NMTOKEN for NED and C++ identifiers, which allow
142
    // ASCII letters, digits and underscore ONLY -- and we validate here accordingly.
143
    //
144
    // This is a deviation from W3C standards, where NMTOKEN would allow letters,
145
    // digits, period, dash, underscore, colon, combining characters, extenders;
146
    // and letters would include international characters as well.
147
    //
148
    const char *s = node->getAttribute(attr);
149
    assert(s);
150
    if (!*s)
151
        return;
152
    if (!opp_isalpha(*s) && *s!='_')
153
        errors->addError(node,"DTD validation error: attribute %s='%s' starts with invalid character (valid NED identifier expected)", attr, node->getAttribute(attr));
154
    while (*++s)
155
        if (!opp_isalpha(*s) && !opp_isdigit(*s) && *s!='_')
156
            {errors->addError(node,"DTD validation error: attribute %s='%s' contains invalid character (valid NED identifier expected)", attr, node->getAttribute(attr)); return;}
157
}
158

    
159
void NEDDTDValidatorBase::checkCommentAttribute(NEDElement *node, const char *attr)
160
{
161
    const char *s = node->getAttribute(attr);
162
    assert(s);
163
    if (!*s)
164
        return;
165
    bool incomment = false;
166
    for (; *s; s++)
167
    {
168
        if (!incomment)
169
        {
170
            if (*s=='/' && *(s+1)=='/')
171
                {s++; incomment = true;}
172
            else if (*s!=' ' && *s!='\t' && *s!='\n' && *s!='\r')
173
                {errors->addError(node,"DTD validation error: attribute %s='%s' does not contain a valid NED comment", attr, node->getAttribute(attr)); return;}
174
        }
175
        else if (incomment)
176
        {
177
            if (*s=='\n' || *s=='\r')
178
                incomment = false;
179
        }
180
    }
181
}
182

    
183