Introduction of BSDArchitecture
[oweals/cde.git] / cde / programs / nsgmls / ExternalId.C
1 /*
2  * CDE - Common Desktop Environment
3  *
4  * Copyright (c) 1993-2012, The Open Group. All rights reserved.
5  *
6  * These libraries and programs are free software; you can
7  * redistribute them and/or modify them under the terms of the GNU
8  * Lesser General Public License as published by the Free Software
9  * Foundation; either version 2 of the License, or (at your option)
10  * any later version.
11  *
12  * These libraries and programs are distributed in the hope that
13  * they will be useful, but WITHOUT ANY WARRANTY; without even the
14  * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15  * PURPOSE. See the GNU Lesser General Public License for more
16  * details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with these librararies and programs; if not, write
20  * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21  * Floor, Boston, MA 02110-1301 USA
22  */
23 /* $XConsortium: ExternalId.C /main/1 1996/07/29 16:51:51 cde-hp $ */
24 // Copyright (c) 1994 James Clark
25 // See the file COPYING for copying permission.
26
27 #ifdef __GNUG__
28 #pragma implementation
29 #endif
30 #include "splib.h"
31 #include "ExternalId.h"
32 #include "CharsetInfo.h"
33 #include "macros.h"
34 #include "ParserMessages.h"
35
36 #ifdef SP_NAMESPACE
37 namespace SP_NAMESPACE {
38 #endif
39
40 ExternalId::ExternalId()
41 : haveSystem_(0), havePublic_(0)
42 {
43 }
44
45 void ExternalId::setSystem(Text &text)
46 {
47   text.swap(system_);
48   haveSystem_ = 1;
49 }
50
51 Boolean ExternalId::setPublic(Text &text, const CharsetInfo &charset,
52                               Char space, const MessageType1 *&error)
53 {
54   havePublic_ = 1;
55   return public_.init(text, charset, space, error);
56 }
57
58 void ExternalId::setLocation(const Location &loc)
59 {
60   loc_ = loc;
61 }
62
63 PublicId::PublicId()
64 : formal_(0)
65 {
66 }
67
68 Boolean PublicId::init(Text &text, const CharsetInfo &charset,
69                        Char space, const MessageType1 *&error)
70 {
71   text.swap(text_);
72   const StringC &str = text_.string();
73   formal_ = 0;
74   const Char *next = str.data();
75   const Char *lim = str.data() + str.size();
76   Char solidus = charset.execToDesc('/');
77   Char minus = charset.execToDesc('-');
78   Char plus = charset.execToDesc('+');
79   const Char *fieldStart;
80   size_t fieldLength;
81   if (!nextField(solidus, next, lim, fieldStart, fieldLength)) {
82     error = &ParserMessages::fpiMissingField;
83     return 0;
84   }
85   if (fieldLength == 1 && (*fieldStart == minus || *fieldStart == plus)) {
86     ownerType_ = (*fieldStart == plus ? registered : unregistered);
87     if (!nextField(solidus, next, lim, fieldStart, fieldLength)) {
88       error = &ParserMessages::fpiMissingField;
89       return 0;
90     }
91   }
92   else
93     ownerType_ = ISO;
94   owner_.assign(fieldStart, fieldLength);
95   if (!nextField(solidus, next, lim, fieldStart, fieldLength)) {
96     error = &ParserMessages::fpiMissingField;
97     return 0;
98   }
99   size_t i;
100   for (i = 0; i < fieldLength; i++)
101     if (fieldStart[i] == space)
102       break;
103   if (i >= fieldLength) {
104     error = &ParserMessages::fpiMissingTextClassSpace;
105     return 0;
106   }
107   StringC textClassString(fieldStart, i);
108   if (!lookupTextClass(textClassString, charset, textClass_)) {
109     error = &ParserMessages::fpiInvalidTextClass;
110     return 0;
111   }
112   i++;                          // skip the space
113   fieldStart += i;
114   fieldLength -= i;
115   if (fieldLength  == 1 && *fieldStart == minus) {
116     unavailable_ = 1;
117     if (!nextField(solidus, next, lim, fieldStart, fieldLength)) {
118       error = &ParserMessages::fpiMissingField;
119       return 0;
120     }
121   }
122   else
123     unavailable_ = 0;
124   description_.assign(fieldStart, fieldLength);
125   if (!nextField(solidus, next, lim, fieldStart, fieldLength)) {
126     error = &ParserMessages::fpiMissingField;
127     return 0;
128   }
129   if (textClass_ != CHARSET) {
130     for (i = 0; i < fieldLength; i++) {
131       UnivChar c;
132       if (!charset.descToUniv(fieldStart[i], c)
133           || c < UnivCharsetDesc::A || c >= UnivCharsetDesc::A + 26) {
134         error = &ParserMessages::fpiInvalidLanguage;
135         return 0;
136       }
137     }
138     // The public text language must be a name.
139     // Names cannot be empty.
140     if (fieldLength == 0) {
141       error = &ParserMessages::fpiInvalidLanguage;
142       return 0;
143     }
144   }
145   languageOrDesignatingSequence_.assign(fieldStart, fieldLength);
146   if (nextField(solidus, next, lim, fieldStart, fieldLength)) {
147     switch (textClass_) {
148     case CAPACITY:
149     case CHARSET:
150     case NOTATION:
151     case SYNTAX:
152       error = &ParserMessages::fpiIllegalDisplayVersion;
153       return 0;
154     default:
155       break;
156     }
157     haveDisplayVersion_ = 1;
158     displayVersion_.assign(fieldStart, fieldLength);
159   }
160   else
161     haveDisplayVersion_ = 0;
162   if (next != 0) {
163     error = &ParserMessages::fpiExtraField;
164     return 0;
165   }
166   formal_ = 1;
167   return 1;
168 }
169
170 Boolean PublicId::nextField(Char solidus,
171                                   const Char *&next,
172                                   const Char *lim,
173                                   const Char *&fieldStart,
174                                   size_t &fieldLength)
175
176 {
177   if (next == 0)
178     return 0;
179   fieldStart = next;
180   for (; next < lim; next++) {
181     if (next[0] == solidus && next + 1 < lim && next[1] == solidus) {
182       fieldLength = next - fieldStart;
183       next += 2;
184       return 1;
185     }
186   }
187   fieldLength = lim - fieldStart;
188   next = 0;
189   return 1;
190 }
191
192 const char *const PublicId::textClasses[] = {
193   "CAPACITY",
194   "CHARSET",
195   "DOCUMENT",
196   "DTD",
197   "ELEMENTS",
198   "ENTITIES",
199   "LPD",
200   "NONSGML",
201   "NOTATION",
202   "SHORTREF",
203   "SUBDOC",
204   "SYNTAX",
205   "TEXT",
206 };
207
208 Boolean PublicId::lookupTextClass(const StringC &str,
209                                         const CharsetInfo &charset,
210                                         TextClass &textClass)
211 {
212   for (size_t i = 0; i < SIZEOF(textClasses); i++)
213     if (str == charset.execToDesc(textClasses[i])) {
214       textClass = TextClass(i);
215       return 1;
216     }
217   return 0;
218 }
219
220 Boolean PublicId::getOwnerType(OwnerType &result) const
221 {
222   if (!formal_)
223     return 0;
224   result = ownerType_;
225   return 1;
226 }
227
228 Boolean PublicId::getOwner(StringC &result) const
229 {
230   if (!formal_)
231     return 0;
232   result = owner_;
233   return 1;
234 }
235
236 Boolean PublicId::getTextClass(TextClass &result) const
237 {
238   if (!formal_)
239     return 0;
240   result = textClass_;
241   return 1;
242 }
243
244 Boolean PublicId::getUnavailable(Boolean &result) const
245 {
246   if (!formal_)
247     return 0;
248   result = unavailable_;
249   return 1;
250 }
251
252 Boolean PublicId::getDescription(StringC &result) const
253 {
254   if (!formal_)
255     return 0;
256   result = description_;
257   return 1;
258 }
259
260 Boolean PublicId::getLanguage(StringC &result) const
261 {
262   if (!formal_ || textClass_ == CHARSET)
263     return 0;
264   result = languageOrDesignatingSequence_;
265   return 1;
266 }
267
268 Boolean PublicId::getDesignatingSequence(StringC &result) const
269 {
270   if (!formal_ || textClass_ != CHARSET)
271     return 0;
272   result = languageOrDesignatingSequence_;
273   return 1;
274 }
275
276 Boolean PublicId::getDisplayVersion(StringC &result) const
277 {
278   if (!formal_)
279     return 0;
280   if (haveDisplayVersion_)
281     result = displayVersion_;
282   return 1;
283 }
284
285 #ifdef SP_NAMESPACE
286 }
287 #endif