1/*
2  Copyright (C) 2000-2008 SKYRIX Software AG
3  Copyright (C) 2008      Helge Hess
4
5  This file is part of SOPE.
6
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
10  later version.
11
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.
16
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
20  02111-1307, USA.
21*/
22
23#include <NGExtensions/NSString+Escaping.h>
24#include "common.h"
25
26@implementation NSString(Escaping)
27
28- (NSString *)stringByApplyingCEscaping {
29  // Unicode!
30  unichar  *src;
31  unichar  *buffer;
32  int      len, pos, srcIdx;
33  NSString *s;
34
35  if ((len = [self length]) == 0)
36    return @"";
37
38  src = malloc(sizeof(unichar) * (len + 2));
39  [self getCharacters:src];
40  src[len] = 0; // zero-terminate
41
42  buffer = malloc(sizeof(unichar) * ((len * 2) + 1));
43
44  for (pos = 0, srcIdx = 0; srcIdx < len; pos++, srcIdx++) {
45    switch (src[srcIdx]) {
46      case '\n':
47        buffer[pos] = '\\'; pos++;
48        buffer[pos] = 'n';
49        break;
50      case '\r':
51        buffer[pos] = '\\'; pos++;
52        buffer[pos] = 'r';
53        break;
54      case '\t':
55        buffer[pos] = '\\'; pos++;
56        buffer[pos] = 't';
57        break;
58
59      default:
60        buffer[pos] = src[srcIdx];
61        break;
62    }
63  }
64  buffer[pos] = '\0';
65
66  s = [NSString stringWithCharacters:buffer length:pos];
67
68  if (buffer != NULL) { free(buffer); buffer = NULL; }
69  if (src    != NULL) { free(src);    src    = NULL; }
70  return s;
71}
72
73- (NSString *)stringByEscapingCharactersFromSet:(NSCharacterSet *)_escSet
74  usingStringEscaping:(id <NGStringEscaping>)_esc
75{
76  NSMutableString *safeString;
77  unsigned length;
78  NSRange  prevRange, escRange;
79  NSRange  todoRange;
80  BOOL     needsEscaping;
81
82  length    = [self length];
83  prevRange = NSMakeRange(0, length);
84  escRange  = [self rangeOfCharacterFromSet:_escSet options:0 range:prevRange];
85
86  needsEscaping = escRange.length > 0 ? YES : NO;
87  if (!needsEscaping)
88    return self; /* cheap */
89
90  safeString = [NSMutableString stringWithCapacity:length];
91
92  do {
93    NSString *s;
94
95    prevRange.length = escRange.location - prevRange.location;
96    if (prevRange.length > 0)
97      [safeString appendString:[self substringWithRange:prevRange]];
98
99    s = [_esc stringByEscapingString:[self substringWithRange:escRange]];
100    if (s != nil)
101        [safeString appendString:s];
102
103    prevRange.location = NSMaxRange(escRange);
104    todoRange.location = prevRange.location;
105    todoRange.length   = length - prevRange.location;
106    escRange           = [self rangeOfCharacterFromSet:_escSet
107                               options:0
108			                         range:todoRange];
109  }
110  while(escRange.length > 0);
111
112  if (todoRange.length > 0)
113    [safeString appendString:[self substringWithRange:todoRange]];
114
115  return safeString;
116}
117
118@end /* NSString(Escaping) */
119