2 Copyright (C) 2000-2004 SKYRIX Software AG
4 This file is part of OpenGroupware.org.
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
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.
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
23 #include <NGExtensions/NSString+Encoding.h>
24 #include <NGExtensions/NSObject+Logs.h>
27 #if NeXT_Foundation_LIBRARY || COCOA_Foundation_LIBRARY
28 # import <CoreFoundation/CoreFoundation.h>
31 # import <Foundation/NSByteOrder.h>
34 // TODO: should move different implementations to different files ...
36 #if NeXT_Foundation_LIBRARY || COCOA_Foundation_LIBRARY
38 @interface NSString(Encoding_PrivateAPI)
39 + (NSStringEncoding)stringEncodingForEncodingNamed:(NSString *)encoding;
42 @implementation NSString(Encoding)
44 + (NSStringEncoding)stringEncodingForEncodingNamed:(NSString *)_encoding
46 CFStringEncoding cfEncoding;
51 _encoding = [_encoding lowercaseString];
52 cfEncoding = CFStringConvertIANACharSetNameToEncoding((CFStringRef)_encoding);
53 if(cfEncoding == kCFStringEncodingInvalidId)
55 return CFStringConvertEncodingToNSStringEncoding(cfEncoding);
58 + (NSString *)stringWithData:(NSData *)_data
59 usingEncodingNamed:(NSString *)_encoding
61 NSStringEncoding encoding;
63 encoding = [NSString stringEncodingForEncodingNamed:_encoding];
64 return [[[NSString alloc] initWithData:_data encoding:encoding] autorelease];
67 - (NSData *)dataUsingEncodingNamed:(NSString *)_encoding {
68 NSStringEncoding encoding;
70 encoding = [NSString stringEncodingForEncodingNamed:_encoding];
71 return [self dataUsingEncoding:encoding];
74 @end /* NSString(Encoding) */
76 #else /* ! NeXT_Foundation_LIBRARY */
78 @implementation NSString(Encoding)
81 static NSString *unicharEncoding = @"UCS-2LE";
83 static NSString *unicharEncoding = @"UCS-2-INTERNAL";
85 static int IconvLogEnabled = -1;
87 static void checkDefaults(void) {
90 if (IconvLogEnabled != -1)
92 ud = [NSUserDefaults standardUserDefaults];
93 IconvLogEnabled = [ud boolForKey:@"IconvLogEnabled"]?1:0;
96 if (NSHostByteOrder() == NS_BigEndian) {
97 NSLog(@"Note: using UCS-2 big endian on Linux.");
98 unicharEncoding = @"UCS-2BE";
101 NSLog(@"Note: using UCS-2 little endian on Linux.");
102 unicharEncoding = @"UCS-2LE";
107 static char *iconv_wrapper(id self, char *_src, unsigned _srcLen,
108 NSString *_fromEncode, NSString *_toEncode,
112 size_t inbytesleft, outbytesleft, write, outlen;
113 const char *fromEncode, *toEncode;
114 char *inbuf, *outbuf, *tm;
119 if (IconvLogEnabled) {
120 [self logWithFormat:@"FromEncode: %@; ToEncode: %@", _fromEncode,
124 _fromEncode = [_fromEncode uppercaseString];
125 _toEncode = [_toEncode uppercaseString];
127 if (0 && [_fromEncode isEqualToString:_toEncode]) {
129 outbuf = calloc(sizeof(char), outlen+1);
131 memcpy(outbuf, _src, _srcLen);
137 fromEncode = [_fromEncode cString];
138 toEncode = [_toEncode cString];
140 type = iconv_open(toEncode, fromEncode);
144 if ((type == (iconv_t)-1)) {
145 [self logWithFormat:@"%s: Could not handle iconv encoding. FromEncoding:%@"
146 @" to encoding:%@", __PRETTY_FUNCTION__, _fromEncode, _toEncode];
147 goto CLEAR_AND_RETURN;
149 inbytesleft = _srcLen;
151 outlen = inbytesleft * 3;
152 outbuf = calloc(outlen + 1, sizeof(char));;
154 outbytesleft = outlen;
156 write = iconv(type, &inbuf, &inbytesleft, &tm, &outbytesleft);
158 if (write == (size_t)-1) {
159 if (errno == EILSEQ) {
160 [self logWithFormat:@"Got invalid multibyte sequence. ToEncode: %@"
161 @" FromEncode: %@.", _toEncode, _fromEncode];
162 if (IconvLogEnabled) {
163 [self logWithFormat:@"ByteSequence:\n%s\n", _src];
165 goto CLEAR_AND_RETURN;
167 else if (errno == EINVAL) {
168 [self logWithFormat:@"Got incomplete multibyte sequence. ToEncode: %@"
169 @" FromEncode: %@", _toEncode, _fromEncode];
171 [self logWithFormat:@"ByteSequence:\n%s\n", _src];
174 else if (errno == E2BIG) {
176 @"Got to small outputbuffer (inbytesleft=%d, outbytesleft=%d, "
177 @"outlen=%d). ToEncode: %@ FromEncode: %@",
178 inbytesleft, outbytesleft, outlen,
179 _toEncode, _fromEncode];
181 [self logWithFormat:@"ByteSequence:\n%s\n", _src];
183 goto CLEAR_AND_RETURN;
186 [self logWithFormat:@"Got unexpected error. ToEncode: %@"
187 @" FromEncode: %@", _toEncode, _fromEncode];
188 goto CLEAR_AND_RETURN;
192 NSLogL(@"outlen %d outbytesleft %d", outlen, outbytesleft);
197 *outLen_ = outlen - outbytesleft;
206 free(outbuf); outbuf = NULL;
211 + (NSString *)stringWithData:(NSData *)_data
212 usingEncodingNamed:(NSString *)_encoding
215 unsigned len, inbufLen;
218 if (![_encoding length])
221 inbufLen = [_data length];
222 inbuf = calloc(sizeof(char), inbufLen + 4);
223 [_data getBytes:inbuf];
226 res = iconv_wrapper(self, inbuf, inbufLen, _encoding, unicharEncoding, &len);
228 result = [[NSString alloc] initWithCharacters:res length:(len / 2)];
229 free(res); res = NULL;
231 if (inbuf) free(inbuf); inbuf = NULL;
232 return [result autorelease];
235 - (NSData *)dataUsingEncodingNamed:(NSString *)_encoding {
238 unsigned inputLen, resLen;
241 if (![_encoding length])
245 inputLen = [self length];
246 chars = calloc(sizeof(unichar), inputLen + 4);
247 [self getCharacters:chars];
249 res = iconv_wrapper(self, (char *)chars, inputLen*2,
250 unicharEncoding, _encoding,
252 if (res) data = [NSData dataWithBytes:res length:resLen];
254 if (chars) free(chars); chars = NULL;
258 @end /* NSString(Encoding) */
260 #endif /* ! NeXT_Foundation_LIBRARY */