merge in latest bas64 changes

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/branches/bitmarkets_changes@38639 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
Riccardo Mottola 2015-06-15 10:29:19 +00:00
parent 6d4af68092
commit 490a0bcbb2
3 changed files with 160 additions and 2 deletions

View file

@ -1,3 +1,9 @@
2015-06-14 Riccardo Mottola <rm@gnu.org>
* Headers/Foundation/NSData.h
* Source/NSData.m
base64EncodedDataWithOptions, base64EncodedStringWithOptions: first implementation
2015-06-08 Richard Frith-Macdonald <rfm@gnu.org>
* Source/NSData.m: be strict about '=' padding only occurring at end

View file

@ -1,5 +1,5 @@
/**
Copyright (C) 1995, 1996, 1997, 2000, 2002 Free Software Foundation, Inc.
Copyright (C) 1995-2015 Free Software Foundation, Inc.
Written by: Andrew Kachites McCallum <mccallum@gnu.ai.mit.edu>
Date: March 1995
@ -147,6 +147,88 @@ decodebase64(unsigned char *dst, const unsigned char *src)
dst[2] = ((src[2] & 0x03) << 6) | (src[3] & 0x3F);
}
static char b64[]
= "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
static NSUInteger
encodebase64(unsigned char **dstRef, const unsigned char *src, NSUInteger length, NSDataBase64EncodingOptions options)
{
unsigned char *dst;
NSUInteger dIndex = 0;
NSUInteger dIndexNoNewLines = 0;
NSUInteger sIndex;
NSUInteger lineLength;
NSUInteger destLen;
lineLength = 0;
if (options & NSDataBase64Encoding64CharacterLineLength)
lineLength = 64;
else if (options & NSDataBase64Encoding76CharacterLineLength)
lineLength = 76;
/* if no EndLine options are set but a line length is given, CR+LF is implied */
if (lineLength && !(options & NSDataBase64EncodingEndLineWithCarriageReturn) && !(options & NSDataBase64EncodingEndLineWithLineFeed))
{
options |= NSDataBase64EncodingEndLineWithCarriageReturn;
options |= NSDataBase64EncodingEndLineWithLineFeed;
}
/* estimate destination length */
destLen = 4 * ((length + 2) / 3);
/* we need to take in account line-endings */
if (lineLength)
{
if (options & (NSDataBase64EncodingEndLineWithCarriageReturn | NSDataBase64EncodingEndLineWithLineFeed))
destLen += (destLen / lineLength)*2;
else
destLen += (destLen / lineLength);
}
#if GS_WITH_GC
dst = NSAllocateCollectable(destLen, 0);
#else
dst = NSZoneMalloc(NSDefaultMallocZone(), destLen);
#endif
for (sIndex = 0; sIndex < length; sIndex += 3)
{
int c0 = src[sIndex];
int c1 = (sIndex+1 < length) ? src[sIndex+1] : 0;
int c2 = (sIndex+2 < length) ? src[sIndex+2] : 0;
dst[dIndex++] = b64[(c0 >> 2) & 077];
dst[dIndex++] = b64[((c0 << 4) & 060) | ((c1 >> 4) & 017)];
dst[dIndex++] = b64[((c1 << 2) & 074) | ((c2 >> 6) & 03)];
dst[dIndex++] = b64[c2 & 077];
dIndexNoNewLines += 4;
if (lineLength && !(dIndexNoNewLines % lineLength) )
{
if (options & NSDataBase64EncodingEndLineWithCarriageReturn)
dst[dIndex++] = '\r';
if (options & NSDataBase64EncodingEndLineWithLineFeed)
dst[dIndex++] = '\n';
}
}
/* If len was not a multiple of 3, then we have encoded too
* many characters. Adjust appropriately.
*/
if (sIndex == length + 1)
{
/* There were only 2 bytes in that last group */
dst[dIndex - 1] = '=';
}
else if (sIndex == length + 2)
{
/* There was only 1 byte in that last group */
dst[dIndex - 1] = '=';
dst[dIndex - 2] = '=';
}
*dstRef = dst;
return dIndex;
}
static BOOL
readContentsOfFile(NSString* path, void** buf, off_t* len, NSZone* zone)
{
@ -221,7 +303,7 @@ readContentsOfFile(NSString* path, void** buf, off_t* len, NSZone* zone)
if (fileLength == 0)
{
unsigned char buf[BUFSIZ];
/*
* Special case ... a file of length zero may be a named pipe or some
* file in the /proc filesystem, which will return us data if we read
@ -959,6 +1041,29 @@ failure:
return [NSData dataWithBytesNoCopy: buffer length: aRange.length];
}
- (NSData *)base64EncodedDataWithOptions:(NSDataBase64EncodingOptions)options
{
void *srcBytes = (void*)[self bytes];
NSUInteger length = [self length];
NSUInteger resLen;
unsigned char *resBytes;
resLen = encodebase64(&resBytes, srcBytes, length, options);
return AUTORELEASE([[NSData alloc] initWithBytesNoCopy: resBytes length: resLen freeWhenDone: YES]);
}
- (NSString *)base64EncodedStringWithOptions:(NSDataBase64EncodingOptions)options
{
void *srcBytes = (void*)[self bytes];
NSUInteger length = [self length];
NSUInteger resLen;
unsigned char *resBytes;
resLen = encodebase64(&resBytes, srcBytes, length, options);
return AUTORELEASE([[NSString alloc] initWithBytesNoCopy: resBytes length: resLen encoding: NSASCIIStringEncoding freeWhenDone: YES]);
}
- (NSUInteger) hash
{
unsigned char buf[64];

View file

@ -7,6 +7,9 @@ int main()
NSAutoreleasePool *arp = [NSAutoreleasePool new];
NSData *data;
NSData *ref;
NSString *str1;
NSString *str2;
NSString *strEnc;
PASS_EXCEPTION([[NSData alloc] initWithBase64EncodedString: nil options: 0],
NSInvalidArgumentException, "nil argument causes exception");
@ -73,6 +76,50 @@ int main()
PASS_EQUAL(data, ref, "base64 decoding vector 8")
[data release];
str1 = @"In principio creavit Deus caelum et terram.\nTerra autem erat inanis et vacua, et tenebrae super faciem abyssi, et spiritus Dei ferebatur super aquas.\nDixitque Deus: \"Fiat lux\". Et facta est lux.";
data = [str1 dataUsingEncoding: NSASCIIStringEncoding];
strEnc = [data base64EncodedStringWithOptions:0];
data = [[NSData alloc] initWithBase64EncodedString: strEnc options: 0];
str2 = [[NSString alloc] initWithData: data encoding: NSASCIIStringEncoding];
PASS_EQUAL(str1, str2, "Encode / Decode no lines")
[str2 release];
str1 = @"In principio creavit Deus caelum et terram.\nTerra autem erat inanis et vacua, et tenebrae super faciem abyssi, et spiritus Dei ferebatur super aquas.\nDixitque Deus: \"Fiat lux\". Et facta est lux.";
data = [str1 dataUsingEncoding: NSASCIIStringEncoding];
strEnc = [data base64EncodedStringWithOptions: (NSDataBase64Encoding64CharacterLineLength | NSDataBase64EncodingEndLineWithLineFeed)];
data = [[NSData alloc] initWithBase64EncodedString: strEnc
options: NSDataBase64DecodingIgnoreUnknownCharacters];
str2 = [[NSString alloc] initWithData: data encoding: NSASCIIStringEncoding];
PASS_EQUAL(str1, str2, "Encode / Decode 64 - LF")
[str2 release];
str1 = @"In principio creavit Deus caelum et terram.\nTerra autem erat inanis et vacua, et tenebrae super faciem abyssi, et spiritus Dei ferebatur super aquas.\nDixitque Deus: \"Fiat lux\". Et facta est lux.";
data = [str1 dataUsingEncoding: NSASCIIStringEncoding];
strEnc = [data base64EncodedStringWithOptions: (NSDataBase64Encoding76CharacterLineLength | NSDataBase64EncodingEndLineWithLineFeed)];
data = [[NSData alloc] initWithBase64EncodedString: strEnc
options: NSDataBase64DecodingIgnoreUnknownCharacters];
str2 = [[NSString alloc] initWithData: data encoding: NSASCIIStringEncoding];
PASS_EQUAL(str1, str2, "Encode / Decode 76 - LF")
[str2 release];
str1 = @"In principio creavit Deus caelum et terram.\nTerra autem erat inanis et vacua, et tenebrae super faciem abyssi, et spiritus Dei ferebatur super aquas.\nDixitque Deus: \"Fiat lux\". Et facta est lux.";
data = [str1 dataUsingEncoding: NSASCIIStringEncoding];
strEnc = [data base64EncodedStringWithOptions: (NSDataBase64Encoding64CharacterLineLength | NSDataBase64EncodingEndLineWithCarriageReturn)];
data = [[NSData alloc] initWithBase64EncodedString: strEnc
options: NSDataBase64DecodingIgnoreUnknownCharacters];
str2 = [[NSString alloc] initWithData: data encoding: NSASCIIStringEncoding];
PASS_EQUAL(str1, str2, "Encode / Decode 64 - CR")
[str2 release];
str1 = @"In principio creavit Deus caelum et terram.\nTerra autem erat inanis et vacua, et tenebrae super faciem abyssi, et spiritus Dei ferebatur super aquas.\nDixitque Deus: \"Fiat lux\". Et facta est lux.";
data = [str1 dataUsingEncoding: NSASCIIStringEncoding];
strEnc = [data base64EncodedStringWithOptions: NSDataBase64Encoding64CharacterLineLength];
data = [[NSData alloc] initWithBase64EncodedString: strEnc
options: NSDataBase64DecodingIgnoreUnknownCharacters];
str2 = [[NSString alloc] initWithData: data encoding: NSASCIIStringEncoding];
PASS_EQUAL(str1, str2, "Encode / Decode 64 - implicit CR LF")
[str2 release];
[arp release]; arp = nil;
return 0;
}