Initial import of the CDE 2.1.30 sources from the Open Group.
[oweals/cde.git] / cde / programs / nsgmls / ExternalId.C
1 /* $XConsortium: ExternalId.C /main/1 1996/07/29 16:51:51 cde-hp $ */
2 // Copyright (c) 1994 James Clark
3 // See the file COPYING for copying permission.
4
5 #ifdef __GNUG__
6 #pragma implementation
7 #endif
8 #include "splib.h"
9 #include "ExternalId.h"
10 #include "CharsetInfo.h"
11 #include "macros.h"
12 #include "ParserMessages.h"
13
14 #ifdef SP_NAMESPACE
15 namespace SP_NAMESPACE {
16 #endif
17
18 ExternalId::ExternalId()
19 : haveSystem_(0), havePublic_(0)
20 {
21 }
22
23 void ExternalId::setSystem(Text &text)
24 {
25   text.swap(system_);
26   haveSystem_ = 1;
27 }
28
29 Boolean ExternalId::setPublic(Text &text, const CharsetInfo &charset,
30                               Char space, const MessageType1 *&error)
31 {
32   havePublic_ = 1;
33   return public_.init(text, charset, space, error);
34 }
35
36 void ExternalId::setLocation(const Location &loc)
37 {
38   loc_ = loc;
39 }
40
41 PublicId::PublicId()
42 : formal_(0)
43 {
44 }
45
46 Boolean PublicId::init(Text &text, const CharsetInfo &charset,
47                        Char space, const MessageType1 *&error)
48 {
49   text.swap(text_);
50   const StringC &str = text_.string();
51   formal_ = 0;
52   const Char *next = str.data();
53   const Char *lim = str.data() + str.size();
54   Char solidus = charset.execToDesc('/');
55   Char minus = charset.execToDesc('-');
56   Char plus = charset.execToDesc('+');
57   const Char *fieldStart;
58   size_t fieldLength;
59   if (!nextField(solidus, next, lim, fieldStart, fieldLength)) {
60     error = &ParserMessages::fpiMissingField;
61     return 0;
62   }
63   if (fieldLength == 1 && (*fieldStart == minus || *fieldStart == plus)) {
64     ownerType_ = (*fieldStart == plus ? registered : unregistered);
65     if (!nextField(solidus, next, lim, fieldStart, fieldLength)) {
66       error = &ParserMessages::fpiMissingField;
67       return 0;
68     }
69   }
70   else
71     ownerType_ = ISO;
72   owner_.assign(fieldStart, fieldLength);
73   if (!nextField(solidus, next, lim, fieldStart, fieldLength)) {
74     error = &ParserMessages::fpiMissingField;
75     return 0;
76   }
77   size_t i;
78   for (i = 0; i < fieldLength; i++)
79     if (fieldStart[i] == space)
80       break;
81   if (i >= fieldLength) {
82     error = &ParserMessages::fpiMissingTextClassSpace;
83     return 0;
84   }
85   StringC textClassString(fieldStart, i);
86   if (!lookupTextClass(textClassString, charset, textClass_)) {
87     error = &ParserMessages::fpiInvalidTextClass;
88     return 0;
89   }
90   i++;                          // skip the space
91   fieldStart += i;
92   fieldLength -= i;
93   if (fieldLength  == 1 && *fieldStart == minus) {
94     unavailable_ = 1;
95     if (!nextField(solidus, next, lim, fieldStart, fieldLength)) {
96       error = &ParserMessages::fpiMissingField;
97       return 0;
98     }
99   }
100   else
101     unavailable_ = 0;
102   description_.assign(fieldStart, fieldLength);
103   if (!nextField(solidus, next, lim, fieldStart, fieldLength)) {
104     error = &ParserMessages::fpiMissingField;
105     return 0;
106   }
107   if (textClass_ != CHARSET) {
108     for (i = 0; i < fieldLength; i++) {
109       UnivChar c;
110       if (!charset.descToUniv(fieldStart[i], c)
111           || c < UnivCharsetDesc::A || c >= UnivCharsetDesc::A + 26) {
112         error = &ParserMessages::fpiInvalidLanguage;
113         return 0;
114       }
115     }
116     // The public text language must be a name.
117     // Names cannot be empty.
118     if (fieldLength == 0) {
119       error = &ParserMessages::fpiInvalidLanguage;
120       return 0;
121     }
122   }
123   languageOrDesignatingSequence_.assign(fieldStart, fieldLength);
124   if (nextField(solidus, next, lim, fieldStart, fieldLength)) {
125     switch (textClass_) {
126     case CAPACITY:
127     case CHARSET:
128     case NOTATION:
129     case SYNTAX:
130       error = &ParserMessages::fpiIllegalDisplayVersion;
131       return 0;
132     default:
133       break;
134     }
135     haveDisplayVersion_ = 1;
136     displayVersion_.assign(fieldStart, fieldLength);
137   }
138   else
139     haveDisplayVersion_ = 0;
140   if (next != 0) {
141     error = &ParserMessages::fpiExtraField;
142     return 0;
143   }
144   formal_ = 1;
145   return 1;
146 }
147
148 Boolean PublicId::nextField(Char solidus,
149                                   const Char *&next,
150                                   const Char *lim,
151                                   const Char *&fieldStart,
152                                   size_t &fieldLength)
153
154 {
155   if (next == 0)
156     return 0;
157   fieldStart = next;
158   for (; next < lim; next++) {
159     if (next[0] == solidus && next + 1 < lim && next[1] == solidus) {
160       fieldLength = next - fieldStart;
161       next += 2;
162       return 1;
163     }
164   }
165   fieldLength = lim - fieldStart;
166   next = 0;
167   return 1;
168 }
169
170 const char *const PublicId::textClasses[] = {
171   "CAPACITY",
172   "CHARSET",
173   "DOCUMENT",
174   "DTD",
175   "ELEMENTS",
176   "ENTITIES",
177   "LPD",
178   "NONSGML",
179   "NOTATION",
180   "SHORTREF",
181   "SUBDOC",
182   "SYNTAX",
183   "TEXT",
184 };
185
186 Boolean PublicId::lookupTextClass(const StringC &str,
187                                         const CharsetInfo &charset,
188                                         TextClass &textClass)
189 {
190   for (size_t i = 0; i < SIZEOF(textClasses); i++)
191     if (str == charset.execToDesc(textClasses[i])) {
192       textClass = TextClass(i);
193       return 1;
194     }
195   return 0;
196 }
197
198 Boolean PublicId::getOwnerType(OwnerType &result) const
199 {
200   if (!formal_)
201     return 0;
202   result = ownerType_;
203   return 1;
204 }
205
206 Boolean PublicId::getOwner(StringC &result) const
207 {
208   if (!formal_)
209     return 0;
210   result = owner_;
211   return 1;
212 }
213
214 Boolean PublicId::getTextClass(TextClass &result) const
215 {
216   if (!formal_)
217     return 0;
218   result = textClass_;
219   return 1;
220 }
221
222 Boolean PublicId::getUnavailable(Boolean &result) const
223 {
224   if (!formal_)
225     return 0;
226   result = unavailable_;
227   return 1;
228 }
229
230 Boolean PublicId::getDescription(StringC &result) const
231 {
232   if (!formal_)
233     return 0;
234   result = description_;
235   return 1;
236 }
237
238 Boolean PublicId::getLanguage(StringC &result) const
239 {
240   if (!formal_ || textClass_ == CHARSET)
241     return 0;
242   result = languageOrDesignatingSequence_;
243   return 1;
244 }
245
246 Boolean PublicId::getDesignatingSequence(StringC &result) const
247 {
248   if (!formal_ || textClass_ != CHARSET)
249     return 0;
250   result = languageOrDesignatingSequence_;
251   return 1;
252 }
253
254 Boolean PublicId::getDisplayVersion(StringC &result) const
255 {
256   if (!formal_)
257     return 0;
258   if (haveDisplayVersion_)
259     result = displayVersion_;
260   return 1;
261 }
262
263 #ifdef SP_NAMESPACE
264 }
265 #endif