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