]> err.no Git - sope/blob - sope-xml/XmlRpc/NSMutableString+XmlRpcDecoder.m
Reworked Xcode build once again.
[sope] / sope-xml / XmlRpc / NSMutableString+XmlRpcDecoder.m
1 // $Id$
2
3 #include "common.h"
4
5 @implementation NSMutableString(XmlRpcDecoder)
6
7 - (void)appendXmlRpcString:(NSString *)_value {
8 #if 1 // TODO: to be tested !
9   unsigned i, j, len;
10   BOOL     didEscape = NO;
11   unichar  *buf, *escbuf = NULL;
12   
13   if ((len = [_value length]) == 0)
14     /* nothing to add ... */
15     return;
16     
17   if (len == 1) {
18     /* a single char */
19     unichar c;
20     
21     switch ((c = [_value characterAtIndex:0])) {
22       case '&': [self appendString:@"&"];  break;
23       case '<': [self appendString:@"&lt;"];   break;
24       case '>': [self appendString:@"&gt;"];   break;
25       case '"': [self appendString:@"&quot;"]; break;
26       default:  [self appendString:_value];    break;
27     }
28     return;
29   }
30   
31   buf = calloc(len + 2, sizeof(unichar));
32   [_value getCharacters:buf];
33   
34   for (i = 0, j = 0; i < len; i++) {
35     switch (buf[i]) {
36       case '&':
37       case '<':
38       case '>':
39       case '"': {
40         didEscape = YES;
41         if (escbuf == NULL) {
42           /* worst case: string consists of quotes */
43           escbuf = calloc(len * 6 + 2, sizeof(unichar));
44           memcpy(escbuf, buf, i * sizeof(unichar));
45           j = i;
46         }
47         escbuf[j++] = '&';
48         switch (buf[i]) {
49           case '&':
50             escbuf[j++] = 'a'; escbuf[j++] = 'm'; escbuf[j++] = 'p';
51             break;
52           case '<':
53             escbuf[j++] = 'l'; escbuf[j++] = 't';
54             break;
55           case '>':
56             escbuf[j++] = 'g'; escbuf[j++] = 't';
57             break;
58           case '"':
59             escbuf[j++] = 'q'; escbuf[j++] = 'u';
60             escbuf[j++] = 'o'; escbuf[j++] = 't';
61             break;
62         }
63         escbuf[j++] = ';';
64         break;
65       }
66       default:
67         if (escbuf)
68           escbuf[j++] = buf[i];
69         break;
70     }
71   }
72   
73   if (escbuf) {
74     NSString *s;
75     
76     s = [[NSString alloc] initWithCharacters:escbuf length:j];
77     [self appendString:s];
78     [s release];
79     free(escbuf);
80   }
81   else
82     [self appendString:_value];
83   
84   if (buf) free(buf);
85 #else
86 #warning UNICODE !!!
87   void (*addBytes)(id,SEL,const char *,unsigned);
88   id            dummy = nil;
89   unsigned      clen;
90   unsigned char *cbuf;
91   unsigned char *cstr;
92
93   if ([_value length] == 0) return;
94
95   clen = [_value cStringLength];
96   if (clen == 0) return; /* nothing to add .. */
97   
98   cbuf = cstr = malloc(clen + 1);
99   [_value getCString:cbuf]; cbuf[clen] = '\0';
100   dummy = [[NSMutableData alloc] initWithCapacity:2*clen];
101
102   addBytes = (void*)[dummy methodForSelector:@selector(appendBytes:length:)];
103   NSAssert(addBytes != NULL, @"could not get appendBytes:length: ..");
104   
105   while (*cstr) {
106     switch (*cstr) {
107       case '&':
108         addBytes(dummy, @selector(appendBytes:length:), "&amp;", 5);
109         break;
110       case '<':
111         addBytes(dummy, @selector(appendBytes:length:), "&lt;", 4);
112         break;
113       case '>':
114         addBytes(dummy, @selector(appendBytes:length:), "&gt;", 4);
115         break;
116       case '"':
117         addBytes(dummy, @selector(appendBytes:length:), "&quot;", 6);
118         break;
119       
120       default:
121         addBytes(dummy, @selector(appendBytes:length:), cstr, 1);
122         break;
123     }
124     cstr++;
125   }
126   free(cbuf);
127   {
128     NSString *tmp = nil;
129     
130     tmp = [[NSString alloc] initWithData:dummy
131                             encoding:[NSString defaultCStringEncoding]];
132     [self appendString:tmp];
133     [tmp release];
134   }
135 #endif
136 }
137
138 @end /* NSMutableString(XmlRpcDecoder) */