2 Copyright (C) 2000-2005 SKYRIX Software AG
4 This file is part of SOPE.
6 SOPE 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
11 SOPE 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.
16 You should have received a copy of the GNU Lesser General Public
17 License along with SOPE; see the file COPYING. If not, write to the
18 Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
22 #include "NSString+misc.h"
25 @interface NSStringVariableBindingException : NSException
28 @implementation NSStringVariableBindingException
31 @implementation NSObject(StringBindings)
33 - (NSString *)valueForStringBinding:(NSString *)_key {
34 if (_key == nil) return nil;
35 return [[self valueForKey:_key] stringValue];
38 @end /* NSObject(StringBindings) */
40 @implementation NSDictionary(StringBindings)
42 - (NSString *)valueForStringBinding:(NSString *)_key {
43 if (_key == nil) return nil;
44 return [[self objectForKey:_key] stringValue];
47 @end /* NSDictionary(StringBindings) */
49 @implementation NSString(misc)
51 - (NSSet *)bindingVariables
53 unsigned len, pos = 0;
54 const char *buf = NULL;
55 NSMutableSet *result = nil;
57 result = [NSMutableSet set];
58 len = [self cStringLength];
64 if (pos + 1 == len) { /* last entry */
65 if (buf[pos] == '$') { /* found $ without end-char */
66 [[[NSStringVariableBindingException alloc]
67 initWithFormat:@"did not find end of variable for string %@", self]
72 if (buf[pos] != '$') {
77 if (buf[pos + 1] == '$') { /* found $$ --> ignore*/
86 pos += 2; /* buf[pos + 1] != '$' */
93 if (pos == len) { /* end of string was reached */
94 [[[NSStringVariableBindingException alloc]
95 initWithFormat:@"didn`t find end of "
96 @"variable for string %@", self]
102 key = [[NSString alloc]
103 initWithCStringNoCopy:(char*)buf + startPos + 1
104 length:pos - startPos - 1
106 [result addObject:key];
111 return [[result copy] autorelease];
114 - (NSString *)stringByReplacingVariablesWithBindings:(id)_bindings
115 stringForUnknownBindings:(NSString *)_unknown
117 unsigned len, pos = 0;
118 const char *buf = NULL;
119 NSMutableString *str = nil;
121 str = [self mutableCopy];
122 len = [str cStringLength];
126 if (pos + 1 == len) { /* last entry */
127 if (buf[pos] == '$') { /* found $ without end-char */
128 [[[NSStringVariableBindingException alloc]
129 initWithFormat:@"did not find end of variable for string %@", self]
134 if (buf[pos] == '$') {
135 if (buf[pos + 1] == '$') { /* found $$ --> $ */
136 [str deleteCharactersInRange:NSMakeRange(pos, 1)];
138 len = [str cStringLength];
141 unsigned startPos = pos;
143 pos += 2; /* buf[pos + 1] != '$' */
150 if (pos == len) { /* end of string was reached */
151 [[[NSStringVariableBindingException alloc]
152 initWithFormat:@"did not find end of variable for string %@",
159 key = [[NSString alloc]
160 initWithCStringNoCopy:(char*)buf + startPos + 1
161 length:pos - startPos - 1
164 if ((value = [_bindings valueForStringBinding:key]) == nil) {
165 if (_unknown == nil) {
166 [[[NSStringVariableBindingException alloc]
167 initWithFormat:@"did not find binding for "
168 @"name %@ in binding-dictionary %@",
169 [key autorelease], _bindings] raise];
174 [key release]; key = nil;
175 [str replaceCharactersInRange:
176 NSMakeRange(startPos, pos - startPos + 1)
179 len = [str cStringLength];
180 pos = startPos - 1 + [value length];
189 [tmp release]; tmp = nil;
191 return [str autorelease];
194 - (NSString *)stringByReplacingVariablesWithBindings:(id)_bindings {
195 return [self stringByReplacingVariablesWithBindings:_bindings
196 stringForUnknownBindings:nil];
199 @end /* NSString(misc) */
202 @implementation NSString(FilePathVersioningMethods)
207 - (NSString *)pathVersion {
210 r = [self rangeOfString:@";"];
212 return ([self length] > r.location)
213 ? [self substringFromIndex:(r.location + r.length)]
219 - (NSString *)stringByDeletingPathVersion {
222 r = [self rangeOfString:@";"];
223 return (r.length > 0)
224 ? [self substringToIndex:r.location]
228 - (NSString *)stringByAppendingPathVersion:(NSString *)_version {
229 return [[self stringByAppendingString:@";"]
230 stringByAppendingString:_version];
233 @end /* NSString(FilePathMethodsVersioning) */
235 @implementation NSString(NGScanning)
237 - (NSRange)rangeOfString:(NSString *)_s
238 skipQuotes:(NSString *)_quotes
239 escapedByChar:(unichar)_escape
242 // TODO: check correctness with invalid input !
243 static NSRange notFound = { 0, 0 };
244 NSCharacterSet *quotes;
245 unsigned i, len, slen;
248 if ((slen = [_s length]) == 0)
250 if ((len = [self length]) < slen) /* to short */
253 if ([_quotes length] == 0)
255 quotes = [NSCharacterSet characterSetWithCharactersInString:_quotes];
257 sc = [_s characterAtIndex:0];
259 for (i = 0; i < len; i++) {
262 c = [self characterAtIndex:i];
265 /* start search section */
267 return NSMakeRange(i, 1);
269 if ([[self substringFromIndex:i] hasPrefix:_s])
270 return NSMakeRange(i, slen);
272 else if ([quotes characterIsMember:c]) {
274 for (i++; i < len && ![quotes characterIsMember:c]; i++) {
276 i++; /* skip next char (eg \') */
286 - (NSRange)rangeOfString:(NSString *)_s skipQuotes:(NSString *)_quotes {
287 return [self rangeOfString:_s skipQuotes:_quotes escapedByChar:'\\'];
290 @end /* NSString(NGScanning) */
293 @implementation NSString(MailQuoting)
295 - (NSString *)stringByApplyingMailQuoting {
298 unichar *sourceBuf, *targetBuf;
300 if ((len = [self length]) == 0)
303 sourceBuf = malloc((len + 4) * sizeof(unichar));
304 [self getCharacters:sourceBuf];
306 for (nl = 0, i = 0; i < len; i++) {
307 if (sourceBuf[i] == '\n')
312 if (sourceBuf) free(sourceBuf);
313 return [@"> " stringByAppendingString:self];
316 targetBuf = malloc((len + 8 + (nl * 3)) * sizeof(unichar));
321 for (i = 0; i < len; i++) {
322 targetBuf[nl] = sourceBuf[i];
325 if (sourceBuf[i] == '\n' && (i + 1 != len)) {
326 targetBuf[nl] = '>'; nl++;
327 targetBuf[nl] = ' '; nl++;
331 s = [[NSString alloc] initWithCharacters:targetBuf length:nl];
332 if (targetBuf) free(targetBuf);
333 if (sourceBuf) free(sourceBuf);
334 return [s autorelease];
337 @end /* NSString(MailQuoting) */
341 void __link_NSString_misc(void) {
342 __link_NSString_misc();