]> err.no Git - sope/blob - sope-xml/SaxObjC/SaxMethodCallHandler.m
removed NGCString
[sope] / sope-xml / SaxObjC / SaxMethodCallHandler.m
1 /*
2   Copyright (C) 2000-2003 SKYRIX Software AG
3
4   This file is part of OGo
5
6   OGo is free software; you can redistribute it and/or modify it under
7   the terms of the GNU Lesser General Public License as published by the
8   Free Software Foundation; either version 2, or (at your option) any
9   later version.
10
11   OGo is distributed in the hope that it will be useful, but WITHOUT ANY
12   WARRANTY; without even the implied warranty of MERCHANTABILITY or
13   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
14   License for more details.
15
16   You should have received a copy of the GNU Lesser General Public
17   License along with OGo; see the file COPYING.  If not, write to the
18   Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
19   02111-1307, USA.
20 */
21 // $Id$
22
23 #include "SaxMethodCallHandler.h"
24 #include "common.h"
25
26 @interface NSObject(ToBeFixed)
27
28 - (id)performSelector:(SEL)_sel
29   withObject:(id)_arg1
30   withObject:(id)_arg2
31   withObject:(id)_arg3;
32
33 @end
34
35 @implementation SaxMethodCallHandler
36
37 static BOOL debugOn = NO;
38
39 - (id)init {
40   if ((self = [super init])) {
41     self->delegate = self;
42     
43     self->fqNameToStartSel = NSCreateMapTable(NSObjectMapKeyCallBacks,
44                                               NSNonOwnedPointerMapValueCallBacks,
45                                               64);
46     self->selName     = [[NSMutableString alloc] initWithCapacity:64];
47     self->tagStack    = [[NSMutableArray alloc] initWithCapacity:16];
48     
49     self->startKey            = @"start_";
50     self->endKey              = @"end_";
51     self->unknownNamespaceKey = @"any_";
52
53     self->ignoreLevel = -1;
54   }
55   return self;
56 }
57
58 - (void)dealloc {
59   NSFreeMapTable(self->fqNameToStartSel);
60   [self->tagStack       release];
61   [self->unknownNamespaceKey release];
62   [self->startKey       release];
63   [self->endKey         release];
64   [self->selName        release];
65   [self->namespaceToKey release];
66   [super dealloc];
67 }
68
69 - (void)registerNamespace:(NSString *)_namespace withKey:(NSString *)_key {
70   if (self->namespaceToKey == nil)
71     self->namespaceToKey = [[NSMutableDictionary alloc] initWithCapacity:16];
72   
73   [self->namespaceToKey setObject:_key forKey:_namespace];
74 }
75
76 - (void)setDelegate:(id)_delegate {
77   NSResetMapTable(self->fqNameToStartSel);
78   
79   self->delegate = _delegate;
80 }
81 - (id)delegate {
82   return self->delegate;
83 }
84
85 - (void)setStartKey:(NSString *)_s {
86   id o = self->startKey;
87   self->startKey = [_s copy];
88   [o release];
89 }
90 - (NSString *)startKey {
91   return self->startKey;
92 }
93
94 - (void)setEndKey:(NSString *)_s {
95   id o = self->endKey;
96   self->endKey = [_s copy];
97   [o release];
98 }
99 - (NSString *)endKey {
100   return self->endKey;
101 }
102
103 - (void)setUnknownNamespaceKey:(NSString *)_s {
104   id o = self->unknownNamespaceKey;
105   self->unknownNamespaceKey = [_s copy];
106   [o release];
107 }
108 - (NSString *)unknownNamespaceKey {
109   return self->unknownNamespaceKey;
110 }
111
112 - (NSArray *)tagStack {
113   return self->tagStack;
114 }
115 - (unsigned)depth {
116   return [self->tagStack count];
117 }
118
119 - (void)ignoreChildren {
120   if (self->ignoreLevel == -1)
121     self->ignoreLevel = [self depth];
122 }
123 - (BOOL)doesIgnoreChildren {
124   if (self->ignoreLevel == -1)
125     return NO;
126   
127   return (int)[self depth] >= self->ignoreLevel ? YES : NO;
128 }
129
130 /* standard Sax callbacks */
131
132 - (void)endDocument {
133   [super endDocument];
134   [selName setString:@""];
135 }
136
137 static inline void _selAdd(SaxMethodCallHandler *self, NSString *_s) {
138   [self->selName appendString:_s];
139 }
140 static inline void _selAddEscaped(SaxMethodCallHandler *self, NSString *_s) {
141   const unsigned char *cstr;
142   register unsigned i, len;
143   BOOL needsEscape = NO;
144   
145   if ((len = [_s cStringLength]) == 0)
146     return;
147   
148   cstr = [_s cString];
149   for (i = 0; i < len; i++) {
150     register unsigned char c = cstr[i];
151
152     if (!(isalnum((int)c) || (c == '_'))) {
153       needsEscape = YES;
154       break;
155     }
156   }
157   
158   if (needsEscape) {
159     unsigned char *buf;
160     unsigned j;
161     NSString *s;
162     
163     buf = malloc(len + 1);
164     for (i = 0, j = 0; i < len; i++) {
165       register unsigned char c = cstr[i];
166       
167       if (isalnum((int)c) || (c == '_')) {
168         if (i > 0) {
169           if (cstr[i - 1] == '-')
170             c = toupper(c);
171         }
172         buf[j] = c;
173         j++;
174       }
175       else {
176         /* do nothing, leave out char */
177       }
178     }
179     buf[j] = '\0';
180     
181     s = [[NSString alloc] initWithCString:buf length:j];
182     [self->selName appendString:s];
183     [s release];
184   }
185   else
186     [self->selName appendString:_s];
187 }
188
189 - (void)startElement:(NSString *)_localName
190   namespace:(NSString *)_ns
191   rawName:(NSString *)_rawName
192   attributes:(id<SaxAttributes>)_attrs
193 {
194   NSString *fqName;
195   NSString *nskey;
196   SEL      sel;
197   
198   fqName = [[NSString alloc] initWithFormat:@"{%@}%@", _ns, _localName];
199   [self->tagStack addObject:fqName];
200   [fqName release]; // still retained by tagStack
201   
202   if ((int)[self depth] > self->ignoreLevel)
203     return;
204   
205   if ((nskey = [self->namespaceToKey objectForKey:_ns]) == nil) {
206     /* unknown namespace */
207     if (debugOn)
208       NSLog(@"unknown namespace key %@ (tag=%@)", _ns, _rawName);
209
210     [self->selName setString:@""];
211     _selAdd(self, self->startKey);
212   }
213   else if ((sel = NSMapGet(self->fqNameToStartSel, fqName))) {
214     /* cached a selector .. */
215     [self->delegate performSelector:sel withObject:_attrs];
216     goto found;
217   }
218   else {
219     [self->selName setString:self->startKey];
220     _selAdd(self, nskey);
221     _selAddEscaped(self, _localName);
222     _selAdd(self, @":");
223     
224     sel = NSSelectorFromString(self->selName);
225     if ([self->delegate respondsToSelector:sel]) {
226       /* ok, found correct selector */
227       [self->delegate performSelector:sel withObject:_attrs];
228       NSMapInsert(self->fqNameToStartSel, fqName, sel);
229       goto found;
230     }
231     
232     /* check for 'start_nskey_unknownTag:attributes:' */
233     [self->selName setString:self->startKey];
234     _selAdd(self, nskey);
235     _selAdd(self, @"unknownTag:attributes:");
236     sel = NSSelectorFromString(self->selName);
237     if ([self->delegate respondsToSelector:sel]) {
238       /* ok, found selector */
239       [self->delegate performSelector:sel
240                       withObject:_localName
241                       withObject:_attrs];
242       goto found;
243     }
244     
245     /* check for 'start_tag:namespace:attributes:' */
246     [self->selName setString:self->startKey];
247     _selAdd(self, @"tag:namespace:attributes:");
248     sel = NSSelectorFromString(self->selName);
249     if ([self->delegate respondsToSelector:sel]) {
250       /* ok, found selector */
251       [self->delegate performSelector:sel
252                       withObject:_localName withObject:_ns
253                       withObject:_attrs];
254       goto found;
255     }
256     
257     /* ignore tag */
258   }
259   
260   if (debugOn) {
261     NSLog(@"%s: ignore tag: %@, sel %@", __PRETTY_FUNCTION__,
262           fqName, self->selName);
263   }
264   return;
265
266  found:
267   ; // required for MacOSX gcc
268 }
269
270 - (void)endElement:(NSString *)_localName
271   namespace:(NSString *)_ns
272   rawName:(NSString *)_rawName
273 {
274   NSString *nskey;
275   SEL      sel;
276   
277   if ((int)[self depth] > self->ignoreLevel) {
278     [self->tagStack removeLastObject];
279     return;
280   }
281   self->ignoreLevel = -1;
282   
283   if ((nskey = [self->namespaceToKey objectForKey:_ns]) == nil) {
284     /* unknown namespace */
285     if (debugOn)
286       NSLog(@"unknown namespace key %@ (tag=%@)", _ns, _rawName);
287     [selName setString:self->endKey];
288   }
289   else {
290     [selName setString:self->endKey];
291     _selAdd(self, nskey);
292     _selAdd(self, _localName);
293     
294     sel = NSSelectorFromString(self->selName);
295     if ([self->delegate respondsToSelector:sel]) {
296       /* ok, found correct selector */
297       [self->delegate performSelector:sel];
298       goto found;
299     }
300     
301     /* check for 'end_nskey_unknownTag:' */
302     [self->selName setString:self->endKey];
303     _selAdd(self, nskey);
304     _selAdd(self, @"unknownTag:");
305     sel = NSSelectorFromString(self->selName);
306     if ([self->delegate respondsToSelector:sel]) {
307       /* ok, found selector */
308       [self->delegate performSelector:sel withObject:_localName];
309       goto found;
310     }
311     
312     /* check for 'end_tag:namespace:attributes:' */
313     [self->selName setString:self->endKey];
314     _selAdd(self, @"tag:namespace:");
315     sel = NSSelectorFromString(self->selName);
316     if ([self->delegate respondsToSelector:sel]) {
317       /* ok, found selector */
318       [self->delegate performSelector:sel withObject:_localName withObject:_ns];
319       goto found;
320     }
321
322     /* didn't find end tag .. */
323   }
324   
325   [self->tagStack removeLastObject];
326   return;
327   
328  found:
329   [self->tagStack removeLastObject];
330 }
331
332 @end /* SaxMethodCallHandler */