2 Copyright (C) 2000-2008 SKYRIX Software AG
3 Copyright (C) 2006-2008 Helge Hess
5 This file is part of SOPE.
7 SOPE is free software; you can redistribute it and/or modify it under
8 the terms of the GNU Lesser General Public License as published by the
9 Free Software Foundation; either version 2, or (at your option) any
12 SOPE is distributed in the hope that it will be useful, but WITHOUT ANY
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
15 License for more details.
17 You should have received a copy of the GNU Lesser General Public
18 License along with SOPE; see the file COPYING. If not, write to the
19 Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
23 #include "NSString+misc.h"
26 @interface NSStringVariableBindingException : NSException
29 @implementation NSStringVariableBindingException
32 @implementation NSObject(StringBindings)
34 - (NSString *)valueForStringBinding:(NSString *)_key {
35 if (_key == nil) return nil;
36 return [[self valueForKeyPath:_key] stringValue];
39 @end /* NSObject(StringBindings) */
41 @implementation NSString(misc)
43 - (NSSet *)bindingVariables
45 unsigned len, pos = 0;
47 NSMutableSet *result = nil;
49 result = [NSMutableSet setWithCapacity:16];
51 wbuf = malloc(sizeof(unichar) * (len + 4));
52 [self getCharacters:wbuf];
57 if (pos + 1 == len) { /* last entry */
58 if (wbuf[pos] == '$') { /* found $ without end-char */
59 [[[NSStringVariableBindingException alloc]
60 initWithFormat:@"did not find end of variable for string %@", self]
65 if (wbuf[pos] != '$') {
70 if (wbuf[pos + 1] == '$') { /* found $$ --> ignore*/
79 pos += 2; /* wbuf[pos + 1] != '$' */
86 if (pos == len) { /* end of string was reached */
87 [[[NSStringVariableBindingException alloc]
88 initWithFormat:@"did not find end of variable for string %@", self]
94 key = [[NSString alloc]
95 initWithCharacters:(unichar *)wbuf + startPos + 1
96 length:(pos - startPos - 1)];
97 [result addObject:key];
102 if (wbuf != NULL) { free(wbuf); wbuf = NULL; }
104 return [[result copy] autorelease];
107 - (NSString *)stringByReplacingVariablesWithBindings:(id)_bindings
108 stringForUnknownBindings:(NSString *)_unknown
110 unsigned len, pos = 0;
111 unichar *wbuf = NULL;
112 NSMutableString *str = nil;
114 str = [self mutableCopy];
116 wbuf = malloc(sizeof(unichar) * (len + 4));
117 [self getCharacters:wbuf];
120 if (pos + 1 == len) { /* last entry */
121 if (wbuf[pos] == '$') { /* found $ without end-char */
122 [[[NSStringVariableBindingException alloc]
123 initWithFormat:@"did not find end of variable for string %@", self]
128 if (wbuf[pos] == '$') {
129 if (wbuf[pos + 1] == '$') { /* found $$ --> $ */
130 [str deleteCharactersInRange:NSMakeRange(pos, 1)];
132 if (wbuf != NULL) { free(wbuf); wbuf = NULL; }
134 wbuf = malloc(sizeof(unichar) * (len + 4));
135 [str getCharacters:wbuf];
138 unsigned startPos = pos;
140 pos += 2; /* wbuf[pos + 1] != '$' */
142 if (wbuf[pos] != '$')
147 if (pos == len) { /* end of string was reached */
148 [[[NSStringVariableBindingException alloc]
149 initWithFormat:@"did not find end of variable for string %@",
156 key = [[NSString alloc]
157 initWithCharacters:(wbuf + startPos + 1)
158 length:(pos - startPos - 1)];
160 if ((value = [_bindings valueForStringBinding:key]) == nil) {
161 if (_unknown == nil) {
162 [[[NSStringVariableBindingException alloc]
163 initWithFormat:@"did not find binding for "
164 @"name %@ in binding-dictionary %@",
165 [key autorelease], _bindings] raise];
170 [key release]; key = nil;
172 [str replaceCharactersInRange:
173 NSMakeRange(startPos, pos - startPos + 1)
176 if (wbuf != NULL) { free(wbuf); wbuf = NULL; }
178 wbuf = malloc(sizeof(unichar) * (len + 4));
179 [str getCharacters:wbuf];
181 pos = startPos - 1 + [value length];
187 if (wbuf != NULL) { free(wbuf); wbuf = NULL; }
191 [tmp release]; tmp = nil;
193 return [str autorelease];
196 - (NSString *)stringByReplacingVariablesWithBindings:(id)_bindings {
197 return [self stringByReplacingVariablesWithBindings:_bindings
198 stringForUnknownBindings:nil];
201 @end /* NSString(misc) */
204 @implementation NSString(FilePathVersioningMethods)
209 - (NSString *)pathVersion {
212 r = [self rangeOfString:@";"];
214 return ([self length] > r.location)
215 ? [self substringFromIndex:(r.location + r.length)]
221 - (NSString *)stringByDeletingPathVersion {
224 r = [self rangeOfString:@";"];
225 return (r.length > 0)
226 ? [self substringToIndex:r.location]
230 - (NSString *)stringByAppendingPathVersion:(NSString *)_version {
231 return [[self stringByAppendingString:@";"]
232 stringByAppendingString:_version];
235 @end /* NSString(FilePathMethodsVersioning) */
237 @implementation NSString(NGScanning)
239 - (NSRange)rangeOfString:(NSString *)_s
240 skipQuotes:(NSString *)_quotes
241 escapedByChar:(unichar)_escape
244 // TODO: check correctness with invalid input !
245 static NSRange notFound = { 0, 0 };
246 NSCharacterSet *quotes;
247 unsigned i, len, slen;
250 if ((slen = [_s length]) == 0)
252 if ((len = [self length]) < slen) /* to short */
255 if ([_quotes length] == 0)
257 quotes = [NSCharacterSet characterSetWithCharactersInString:_quotes];
259 sc = [_s characterAtIndex:0];
261 for (i = 0; i < len; i++) {
264 c = [self characterAtIndex:i];
267 /* start search section */
269 return NSMakeRange(i, 1);
271 if ([[self substringFromIndex:i] hasPrefix:_s])
272 return NSMakeRange(i, slen);
274 else if ([quotes characterIsMember:c]) {
277 c = [self characterAtIndex:i];
278 for (; i < len && ![quotes characterIsMember:c]; i++) {
279 c = [self characterAtIndex:i];
281 i++; /* skip next char (eg \') */
291 - (NSRange)rangeOfString:(NSString *)_s skipQuotes:(NSString *)_quotes {
292 return [self rangeOfString:_s skipQuotes:_quotes escapedByChar:'\\'];
295 @end /* NSString(NGScanning) */
298 @implementation NSString(MailQuoting)
300 - (NSString *)stringByApplyingMailQuoting {
303 unichar *sourceBuf, *targetBuf;
305 if ((len = [self length]) == 0)
308 sourceBuf = malloc((len + 4) * sizeof(unichar));
309 [self getCharacters:sourceBuf];
311 for (nl = 0, i = 0; i < len; i++) {
312 if (sourceBuf[i] == '\n')
317 if (sourceBuf) free(sourceBuf);
318 return [@"> " stringByAppendingString:self];
321 targetBuf = malloc((len + 8 + (nl * 3)) * sizeof(unichar));
326 for (i = 0; i < len; i++) {
327 targetBuf[nl] = sourceBuf[i];
330 if (sourceBuf[i] == '\n' && (i + 1 != len)) {
331 targetBuf[nl] = '>'; nl++;
332 targetBuf[nl] = ' '; nl++;
336 s = [[NSString alloc] initWithCharacters:targetBuf length:nl];
337 if (targetBuf) free(targetBuf);
338 if (sourceBuf) free(sourceBuf);
339 return [s autorelease];
342 @end /* NSString(MailQuoting) */
346 void __link_NSString_misc(void) {
347 __link_NSString_misc();