Repair to Code Final Commit

This commit is contained in:
Alexander Davis
2017-05-06 02:17:51 +01:00
parent 219378c12f
commit d2046d4c7c
752 changed files with 65519 additions and 222 deletions

View File

@@ -0,0 +1,100 @@
//
// GTMDebugSelectorValidation.h
//
// This file should only be included within an implimation file. In any
// function that takes an object and selector to invoke, you should call:
//
// GTMAssertSelectorNilOrImplementedWithArguments(obj, sel, @encode(arg1type), ..., NULL)
// or
// GTMAssertSelectorNilOrImplementedWithReturnTypeAndArguments(obj, sel, @encode(returnType), @encode(arg1type), ..., NULL)
//
// This will then validate that the selector is defined and using the right
// type(s), this can help catch errors much earlier then waiting for the
// selector to actually fire (and in the case of error selectors, might never
// really be tested until in the field).
//
// Copyright 2007-2008 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not
// use this file except in compliance with the License. You may obtain a copy
// of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations under
// the License.
//
#if DEBUG
#import <stdarg.h>
#import "GTMDefines.h"
static void GTMAssertSelectorNilOrImplementedWithReturnTypeAndArguments(id obj, SEL sel, const char *retType, ...) {
// verify that the object's selector is implemented with the proper
// number and type of arguments
va_list argList;
va_start(argList, retType);
if (obj && sel) {
// check that the selector is implemented
_GTMDevAssert([obj respondsToSelector:sel],
@"\"%@\" selector \"%@\" is unimplemented or misnamed",
NSStringFromClass([obj class]),
NSStringFromSelector(sel));
const char *expectedArgType;
NSUInteger argCount = 2; // skip self and _cmd
NSMethodSignature *sig = [obj methodSignatureForSelector:sel];
// check that each expected argument is present and of the correct type
while ((expectedArgType = va_arg(argList, const char*)) != 0) {
if ([sig numberOfArguments] > argCount) {
const char *foundArgType = [sig getArgumentTypeAtIndex:argCount];
_GTMDevAssert(0 == strncmp(foundArgType, expectedArgType, strlen(expectedArgType)),
@"\"%@\" selector \"%@\" argument %u should be type %s",
NSStringFromClass([obj class]),
NSStringFromSelector(sel),
(uint32_t)(argCount - 2),
expectedArgType);
}
argCount++;
}
// check that the proper number of arguments are present in the selector
_GTMDevAssert(argCount == [sig numberOfArguments],
@"\"%@\" selector \"%@\" should have %u arguments",
NSStringFromClass([obj class]),
NSStringFromSelector(sel),
(uint32_t)(argCount - 2));
// if asked, validate the return type
if (retType && (strcmp("gtm_skip_return_test", retType) != 0)) {
const char *foundRetType = [sig methodReturnType];
_GTMDevAssert(0 == strncmp(foundRetType, retType, strlen(retType)),
@"\"%@\" selector \"%@\" return type should be type %s",
NSStringFromClass([obj class]),
NSStringFromSelector(sel),
retType);
}
}
va_end(argList);
}
#define GTMAssertSelectorNilOrImplementedWithArguments(obj, sel, ...) \
GTMAssertSelectorNilOrImplementedWithReturnTypeAndArguments((obj), (sel), "gtm_skip_return_test", __VA_ARGS__)
#else // DEBUG
// make it go away if not debug
#define GTMAssertSelectorNilOrImplementedWithReturnTypeAndArguments(obj, sel, retType, ...) do { } while (0)
#define GTMAssertSelectorNilOrImplementedWithArguments(obj, sel, ...) do { } while (0)
#endif // DEBUG

View File

@@ -0,0 +1,44 @@
//
// GTMDebugThreadValidation.h
//
// Copyright 2016 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not
// use this file except in compliance with the License. You may obtain a copy
// of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations under
// the License.
//
#import "GTMDefines.h"
#import <Foundation/Foundation.h>
// GTMCheckCurrentQueue, GTMIsCurrentQueue
//
// GTMCheckCurrentQueue takes a target queue and uses _GTMDevAssert to
// report if that is not the currently executing queue.
//
// GTMIsCurrentQueue takes a target queue and returns true if the target queue
// is the currently executing dispatch queue. This can be passed to another
// assertion call in debug builds; it should never be used in release code.
//
// The dispatch queue must have a label.
#define GTMCheckCurrentQueue(targetQueue) \
_GTMDevAssert(GTMIsCurrentQueue(targetQueue), \
@"Current queue is %s (expected %s)", \
_GTMQueueName(DISPATCH_CURRENT_QUEUE_LABEL), \
_GTMQueueName(targetQueue))
#define GTMIsCurrentQueue(targetQueue) \
(strcmp(_GTMQueueName(DISPATCH_CURRENT_QUEUE_LABEL), \
_GTMQueueName(targetQueue)) == 0)
#define _GTMQueueName(queue) \
(strlen(dispatch_queue_get_label(queue)) > 0 ? \
dispatch_queue_get_label(queue) : "unnamed")

View File

@@ -0,0 +1,69 @@
//
// GTMMethodCheck.h
//
// Copyright 2006-2016 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not
// use this file except in compliance with the License. You may obtain a copy
// of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations under
// the License.
//
#import <Foundation/Foundation.h>
#import <stdio.h>
#import <sysexits.h>
/// A macro for enforcing debug time checks to make sure all required methods are linked in
//
// When using categories, it can be very easy to forget to include the
// implementation of a category.
// Let's say you had a class foo that depended on method bar of class baz, and
// method bar was implemented as a member of a category.
// You could add the following code:
//
// GTM_METHOD_CHECK(baz, bar)
//
// and the code would check to make sure baz was implemented just before main
// was called. This works for both dynamic libraries, and executables.
//
//
// This is not compiled into release builds.
#ifdef DEBUG
// This is the "magic".
// A) we need a multi layer define here so that the preprocessor expands
// __LINE__ the way we want it. We need __LINE__ so that each of our
// GTM_METHOD_CHECKs generates a unique function name.
#define GTM_METHOD_CHECK(class, method) GTM_METHOD_CHECK_INNER(class, method, __LINE__)
#define GTM_METHOD_CHECK_INNER(class, method, line) \
GTM_METHOD_CHECK_INNER_INNER(class, method, line)
// B) define a function that is called at startup to check that |class| has an
// implementation for |method| (either a class method or an instance method).
#define GTM_METHOD_CHECK_INNER_INNER(class, method, line) \
__attribute__ ((constructor, visibility("hidden"))) \
static void xxGTMMethodCheckMethod ## class ## line () { \
@autoreleasepool { \
if (![class instancesRespondToSelector:@selector(method)] \
&& ![class respondsToSelector:@selector(method)]) { \
fprintf(stderr, "%s:%d: error: We need method '%s' to be linked in for class '%s'\n", \
__FILE__, line, #method, #class); \
exit(EX_SOFTWARE); \
} \
} \
}
#else // DEBUG
// Do nothing in release.
#define GTM_METHOD_CHECK(class, method)
#endif // DEBUG

View File

@@ -0,0 +1,199 @@
//
// GTMNSData+zlib.h
//
// Copyright 2007-2008 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not
// use this file except in compliance with the License. You may obtain a copy
// of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations under
// the License.
//
#import <Foundation/Foundation.h>
#import "GTMDefines.h"
/// Helpers for dealing w/ zlib inflate/deflate calls.
@interface NSData (GTMZLibAdditions)
// NOTE: For 64bit, none of these apis handle input sizes >32bits, they will
// return nil when given such data. To handle data of that size you really
// should be streaming it rather then doing it all in memory.
#pragma mark Gzip Compression
/// Return an autoreleased NSData w/ the result of gzipping the bytes.
//
// Uses the default compression level.
+ (NSData *)gtm_dataByGzippingBytes:(const void *)bytes
length:(NSUInteger)length;
+ (NSData *)gtm_dataByGzippingBytes:(const void *)bytes
length:(NSUInteger)length
error:(NSError **)error;
/// Return an autoreleased NSData w/ the result of gzipping the payload of |data|.
//
// Uses the default compression level.
+ (NSData *)gtm_dataByGzippingData:(NSData *)data __attribute__((deprecated("Use error variant")));
+ (NSData *)gtm_dataByGzippingData:(NSData *)data
error:(NSError **)error;
/// Return an autoreleased NSData w/ the result of gzipping the bytes using |level| compression level.
//
// |level| can be 1-9, any other values will be clipped to that range.
+ (NSData *)gtm_dataByGzippingBytes:(const void *)bytes
length:(NSUInteger)length
compressionLevel:(int)level __attribute__((deprecated("Use error variant")));
+ (NSData *)gtm_dataByGzippingBytes:(const void *)bytes
length:(NSUInteger)length
compressionLevel:(int)level
error:(NSError **)error;
/// Return an autoreleased NSData w/ the result of gzipping the payload of |data| using |level| compression level.
+ (NSData *)gtm_dataByGzippingData:(NSData *)data
compressionLevel:(int)level __attribute__((deprecated("Use error variant")));
+ (NSData *)gtm_dataByGzippingData:(NSData *)data
compressionLevel:(int)level
error:(NSError **)error;
#pragma mark Zlib "Stream" Compression
// NOTE: deflate is *NOT* gzip. deflate is a "zlib" stream. pick which one
// you really want to create. (the inflate api will handle either)
/// Return an autoreleased NSData w/ the result of deflating the bytes.
//
// Uses the default compression level.
+ (NSData *)gtm_dataByDeflatingBytes:(const void *)bytes
length:(NSUInteger)length __attribute__((deprecated("Use error variant")));
+ (NSData *)gtm_dataByDeflatingBytes:(const void *)bytes
length:(NSUInteger)length
error:(NSError **)error;
/// Return an autoreleased NSData w/ the result of deflating the payload of |data|.
//
// Uses the default compression level.
+ (NSData *)gtm_dataByDeflatingData:(NSData *)data __attribute__((deprecated("Use error variant")));
+ (NSData *)gtm_dataByDeflatingData:(NSData *)data
error:(NSError **)error;
/// Return an autoreleased NSData w/ the result of deflating the bytes using |level| compression level.
//
// |level| can be 1-9, any other values will be clipped to that range.
+ (NSData *)gtm_dataByDeflatingBytes:(const void *)bytes
length:(NSUInteger)length
compressionLevel:(int)level __attribute__((deprecated("Use error variant")));
+ (NSData *)gtm_dataByDeflatingBytes:(const void *)bytes
length:(NSUInteger)length
compressionLevel:(int)level
error:(NSError **)error;
/// Return an autoreleased NSData w/ the result of deflating the payload of |data| using |level| compression level.
+ (NSData *)gtm_dataByDeflatingData:(NSData *)data
compressionLevel:(int)level __attribute__((deprecated("Use error variant")));
+ (NSData *)gtm_dataByDeflatingData:(NSData *)data
compressionLevel:(int)level
error:(NSError **)error;
#pragma mark Uncompress of Gzip or Zlib
/// Return an autoreleased NSData w/ the result of decompressing the bytes.
//
// The bytes to decompress can be zlib or gzip payloads.
+ (NSData *)gtm_dataByInflatingBytes:(const void *)bytes
length:(NSUInteger)length __attribute__((deprecated("Use error variant")));
+ (NSData *)gtm_dataByInflatingBytes:(const void *)bytes
length:(NSUInteger)length
error:(NSError **)error;
/// Return an autoreleased NSData w/ the result of decompressing the payload of |data|.
//
// The data to decompress can be zlib or gzip payloads.
+ (NSData *)gtm_dataByInflatingData:(NSData *)data __attribute__((deprecated("Use error variant")));
+ (NSData *)gtm_dataByInflatingData:(NSData *)data
error:(NSError **)error;
#pragma mark "Raw" Compression Support
// NOTE: raw deflate is *NOT* gzip or deflate. it does not include a header
// of any form and should only be used within streams here an external crc/etc.
// is done to validate the data. The RawInflate apis can be used on data
// processed like this.
/// Return an autoreleased NSData w/ the result of *raw* deflating the bytes.
//
// Uses the default compression level.
// *No* header is added to the resulting data.
+ (NSData *)gtm_dataByRawDeflatingBytes:(const void *)bytes
length:(NSUInteger)length __attribute__((deprecated("Use error variant")));
+ (NSData *)gtm_dataByRawDeflatingBytes:(const void *)bytes
length:(NSUInteger)length
error:(NSError **)error;
/// Return an autoreleased NSData w/ the result of *raw* deflating the payload of |data|.
//
// Uses the default compression level.
// *No* header is added to the resulting data.
+ (NSData *)gtm_dataByRawDeflatingData:(NSData *)data __attribute__((deprecated("Use error variant")));
+ (NSData *)gtm_dataByRawDeflatingData:(NSData *)data
error:(NSError **)error;
/// Return an autoreleased NSData w/ the result of *raw* deflating the bytes using |level| compression level.
//
// |level| can be 1-9, any other values will be clipped to that range.
// *No* header is added to the resulting data.
+ (NSData *)gtm_dataByRawDeflatingBytes:(const void *)bytes
length:(NSUInteger)length
compressionLevel:(int)level __attribute__((deprecated("Use error variant")));
+ (NSData *)gtm_dataByRawDeflatingBytes:(const void *)bytes
length:(NSUInteger)length
compressionLevel:(int)level
error:(NSError **)error;
/// Return an autoreleased NSData w/ the result of *raw* deflating the payload of |data| using |level| compression level.
// *No* header is added to the resulting data.
+ (NSData *)gtm_dataByRawDeflatingData:(NSData *)data
compressionLevel:(int)level __attribute__((deprecated("Use error variant")));
+ (NSData *)gtm_dataByRawDeflatingData:(NSData *)data
compressionLevel:(int)level
error:(NSError **)error;
/// Return an autoreleased NSData w/ the result of *raw* decompressing the bytes.
//
// The data to decompress, it should *not* have any header (zlib nor gzip).
+ (NSData *)gtm_dataByRawInflatingBytes:(const void *)bytes
length:(NSUInteger)length __attribute__((deprecated("Use error variant")));
+ (NSData *)gtm_dataByRawInflatingBytes:(const void *)bytes
length:(NSUInteger)length
error:(NSError **)error;
/// Return an autoreleased NSData w/ the result of *raw* decompressing the payload of |data|.
//
// The data to decompress, it should *not* have any header (zlib nor gzip).
+ (NSData *)gtm_dataByRawInflatingData:(NSData *)data __attribute__((deprecated("Use error variant")));
+ (NSData *)gtm_dataByRawInflatingData:(NSData *)data
error:(NSError **)error;
@end
FOUNDATION_EXPORT NSString *const GTMNSDataZlibErrorDomain;
FOUNDATION_EXPORT NSString *const GTMNSDataZlibErrorKey; // NSNumber
FOUNDATION_EXPORT NSString *const GTMNSDataZlibRemainingBytesKey; // NSNumber
typedef NS_ENUM(NSInteger, GTMNSDataZlibError) {
GTMNSDataZlibErrorGreaterThan32BitsToCompress = 1024,
// An internal zlib error.
// GTMNSDataZlibErrorKey will contain the error value.
// NSLocalizedDescriptionKey may contain an error string from zlib.
// Look in zlib.h for list of errors.
GTMNSDataZlibErrorInternal,
// There was left over data in the buffer that was not used.
// GTMNSDataZlibRemainingBytesKey will contain number of remaining bytes.
GTMNSDataZlibErrorDataRemaining
};

View File

@@ -0,0 +1,531 @@
//
// GTMNSData+zlib.m
//
// Copyright 2007-2008 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not
// use this file except in compliance with the License. You may obtain a copy
// of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations under
// the License.
//
#import "GTMNSData+zlib.h"
#import <zlib.h>
#import "GTMDefines.h"
#define kChunkSize 1024
NSString *const GTMNSDataZlibErrorDomain = @"com.google.GTMNSDataZlibErrorDomain";
NSString *const GTMNSDataZlibErrorKey = @"GTMNSDataZlibErrorKey";
NSString *const GTMNSDataZlibRemainingBytesKey = @"GTMNSDataZlibRemainingBytesKey";
typedef enum {
CompressionModeZlib,
CompressionModeGzip,
CompressionModeRaw,
} CompressionMode;
@interface NSData (GTMZlibAdditionsPrivate)
+ (NSData *)gtm_dataByCompressingBytes:(const void *)bytes
length:(NSUInteger)length
compressionLevel:(int)level
mode:(CompressionMode)mode
error:(NSError **)error;
+ (NSData *)gtm_dataByInflatingBytes:(const void *)bytes
length:(NSUInteger)length
isRawData:(BOOL)isRawData
error:(NSError **)error;
@end
@implementation NSData (GTMZlibAdditionsPrivate)
+ (NSData *)gtm_dataByCompressingBytes:(const void *)bytes
length:(NSUInteger)length
compressionLevel:(int)level
mode:(CompressionMode)mode
error:(NSError **)error {
if (!bytes || !length) {
return nil;
}
#if defined(__LP64__) && __LP64__
// Don't support > 32bit length for 64 bit, see note in header.
if (length > UINT_MAX) {
if (error) {
*error = [NSError errorWithDomain:GTMNSDataZlibErrorDomain
code:GTMNSDataZlibErrorGreaterThan32BitsToCompress
userInfo:nil];
}
return nil;
}
#endif
if (level == Z_DEFAULT_COMPRESSION) {
// the default value is actually outside the range, so we have to let it
// through specifically.
} else if (level < Z_BEST_SPEED) {
level = Z_BEST_SPEED;
} else if (level > Z_BEST_COMPRESSION) {
level = Z_BEST_COMPRESSION;
}
z_stream strm;
bzero(&strm, sizeof(z_stream));
int memLevel = 8; // the default
int windowBits = 15; // the default
switch (mode) {
case CompressionModeZlib:
// nothing to do
break;
case CompressionModeGzip:
windowBits += 16; // enable gzip header instead of zlib header
break;
case CompressionModeRaw:
windowBits *= -1; // Negative to mean no header.
break;
}
int retCode;
if ((retCode = deflateInit2(&strm, level, Z_DEFLATED, windowBits,
memLevel, Z_DEFAULT_STRATEGY)) != Z_OK) {
// COV_NF_START - no real way to force this in a unittest (we guard all args)
if (error) {
NSDictionary *userInfo = [NSDictionary dictionaryWithObject:[NSNumber numberWithInt:retCode]
forKey:GTMNSDataZlibErrorKey];
*error = [NSError errorWithDomain:GTMNSDataZlibErrorDomain
code:GTMNSDataZlibErrorInternal
userInfo:userInfo];
}
return nil;
// COV_NF_END
}
// hint the size at 1/4 the input size
NSMutableData *result = [NSMutableData dataWithCapacity:(length/4)];
unsigned char output[kChunkSize];
// setup the input
strm.avail_in = (unsigned int)length;
strm.next_in = (unsigned char*)bytes;
// loop to collect the data
do {
// update what we're passing in
strm.avail_out = kChunkSize;
strm.next_out = output;
retCode = deflate(&strm, Z_FINISH);
if ((retCode != Z_OK) && (retCode != Z_STREAM_END)) {
// COV_NF_START - no real way to force this in a unittest
// (in inflate, we can feed bogus/truncated data to test, but an error
// here would be some internal issue w/in zlib, and there isn't any real
// way to test it)
if (error) {
NSDictionary *userInfo = [NSDictionary dictionaryWithObject:[NSNumber numberWithInt:retCode]
forKey:GTMNSDataZlibErrorKey];
*error = [NSError errorWithDomain:GTMNSDataZlibErrorDomain
code:GTMNSDataZlibErrorInternal
userInfo:userInfo];
}
deflateEnd(&strm);
return nil;
// COV_NF_END
}
// collect what we got
unsigned gotBack = kChunkSize - strm.avail_out;
if (gotBack > 0) {
[result appendBytes:output length:gotBack];
}
} while (retCode == Z_OK);
// if the loop exits, we used all input and the stream ended
_GTMDevAssert(strm.avail_in == 0,
@"thought we finished deflate w/o using all input, %u bytes left",
strm.avail_in);
_GTMDevAssert(retCode == Z_STREAM_END,
@"thought we finished deflate w/o getting a result of stream end, code %d",
retCode);
// clean up
deflateEnd(&strm);
return result;
} // gtm_dataByCompressingBytes:length:compressionLevel:useGzip:
+ (NSData *)gtm_dataByInflatingBytes:(const void *)bytes
length:(NSUInteger)length
isRawData:(BOOL)isRawData
error:(NSError **)error {
if (!bytes || !length) {
return nil;
}
#if defined(__LP64__) && __LP64__
// Don't support > 32bit length for 64 bit, see note in header.
if (length > UINT_MAX) {
return nil;
}
#endif
z_stream strm;
bzero(&strm, sizeof(z_stream));
// setup the input
strm.avail_in = (unsigned int)length;
strm.next_in = (unsigned char*)bytes;
int windowBits = 15; // 15 to enable any window size
if (isRawData) {
windowBits *= -1; // make it negative to signal no header.
} else {
windowBits += 32; // and +32 to enable zlib or gzip header detection.
}
int retCode;
if ((retCode = inflateInit2(&strm, windowBits)) != Z_OK) {
// COV_NF_START - no real way to force this in a unittest (we guard all args)
if (error) {
NSDictionary *userInfo = [NSDictionary dictionaryWithObject:[NSNumber numberWithInt:retCode]
forKey:GTMNSDataZlibErrorKey];
*error = [NSError errorWithDomain:GTMNSDataZlibErrorDomain
code:GTMNSDataZlibErrorInternal
userInfo:userInfo];
}
return nil;
// COV_NF_END
}
// hint the size at 4x the input size
NSMutableData *result = [NSMutableData dataWithCapacity:(length*4)];
unsigned char output[kChunkSize];
// loop to collect the data
do {
// update what we're passing in
strm.avail_out = kChunkSize;
strm.next_out = output;
retCode = inflate(&strm, Z_NO_FLUSH);
if ((retCode != Z_OK) && (retCode != Z_STREAM_END)) {
if (error) {
NSMutableDictionary *userInfo =
[NSMutableDictionary dictionaryWithObject:[NSNumber numberWithInt:retCode]
forKey:GTMNSDataZlibErrorKey];
if (strm.msg) {
NSString *message = [NSString stringWithUTF8String:strm.msg];
if (message) {
[userInfo setObject:message forKey:NSLocalizedDescriptionKey];
}
}
*error = [NSError errorWithDomain:GTMNSDataZlibErrorDomain
code:GTMNSDataZlibErrorInternal
userInfo:userInfo];
}
inflateEnd(&strm);
return nil;
}
// collect what we got
unsigned gotBack = kChunkSize - strm.avail_out;
if (gotBack > 0) {
[result appendBytes:output length:gotBack];
}
} while (retCode == Z_OK);
// make sure there wasn't more data tacked onto the end of a valid compressed
// stream.
if (strm.avail_in != 0) {
if (error) {
NSDictionary *userInfo =
[NSDictionary dictionaryWithObject:[NSNumber numberWithUnsignedInt:strm.avail_in]
forKey:GTMNSDataZlibRemainingBytesKey];
*error = [NSError errorWithDomain:GTMNSDataZlibErrorDomain
code:GTMNSDataZlibErrorDataRemaining
userInfo:userInfo];
}
result = nil;
}
// the only way out of the loop was by hitting the end of the stream
_GTMDevAssert(retCode == Z_STREAM_END,
@"thought we finished inflate w/o getting a result of stream end, code %d",
retCode);
// clean up
inflateEnd(&strm);
return result;
} // gtm_dataByInflatingBytes:length:windowBits:
@end
@implementation NSData (GTMZLibAdditions)
+ (NSData *)gtm_dataByGzippingBytes:(const void *)bytes
length:(NSUInteger)length {
return [self gtm_dataByGzippingBytes:bytes length:length error:NULL];
} // gtm_dataByGzippingBytes:length:
+ (NSData *)gtm_dataByGzippingBytes:(const void *)bytes
length:(NSUInteger)length
error:(NSError **)error {
return [self gtm_dataByCompressingBytes:bytes
length:length
compressionLevel:Z_DEFAULT_COMPRESSION
mode:CompressionModeGzip
error:error];
} // gtm_dataByGzippingBytes:length:error:
+ (NSData *)gtm_dataByGzippingData:(NSData *)data {
return [self gtm_dataByGzippingData:data error:NULL];
} // gtm_dataByGzippingData:
+ (NSData *)gtm_dataByGzippingData:(NSData *)data error:(NSError **)error {
return [self gtm_dataByCompressingBytes:[data bytes]
length:[data length]
compressionLevel:Z_DEFAULT_COMPRESSION
mode:CompressionModeGzip
error:error];
} // gtm_dataByGzippingData:error:
+ (NSData *)gtm_dataByGzippingBytes:(const void *)bytes
length:(NSUInteger)length
compressionLevel:(int)level {
return [self gtm_dataByGzippingBytes:bytes
length:length
compressionLevel:level
error:NULL];
} // gtm_dataByGzippingBytes:length:level:
+ (NSData *)gtm_dataByGzippingBytes:(const void *)bytes
length:(NSUInteger)length
compressionLevel:(int)level
error:(NSError **)error{
return [self gtm_dataByCompressingBytes:bytes
length:length
compressionLevel:level
mode:CompressionModeGzip
error:error];
} // gtm_dataByGzippingBytes:length:level:error
+ (NSData *)gtm_dataByGzippingData:(NSData *)data
compressionLevel:(int)level {
return [self gtm_dataByGzippingData:data
compressionLevel:level
error:NULL];
} // gtm_dataByGzippingData:level:
+ (NSData *)gtm_dataByGzippingData:(NSData *)data
compressionLevel:(int)level
error:(NSError **)error{
return [self gtm_dataByCompressingBytes:[data bytes]
length:[data length]
compressionLevel:level
mode:CompressionModeGzip
error:error];
} // gtm_dataByGzippingData:level:error
#pragma mark -
+ (NSData *)gtm_dataByDeflatingBytes:(const void *)bytes
length:(NSUInteger)length {
return [self gtm_dataByDeflatingBytes:bytes
length:length
error:NULL];
} // gtm_dataByDeflatingBytes:length:
+ (NSData *)gtm_dataByDeflatingBytes:(const void *)bytes
length:(NSUInteger)length
error:(NSError **)error{
return [self gtm_dataByCompressingBytes:bytes
length:length
compressionLevel:Z_DEFAULT_COMPRESSION
mode:CompressionModeZlib
error:error];
} // gtm_dataByDeflatingBytes:length:error
+ (NSData *)gtm_dataByDeflatingData:(NSData *)data {
return [self gtm_dataByDeflatingData:data error:NULL];
} // gtm_dataByDeflatingData:
+ (NSData *)gtm_dataByDeflatingData:(NSData *)data error:(NSError **)error {
return [self gtm_dataByCompressingBytes:[data bytes]
length:[data length]
compressionLevel:Z_DEFAULT_COMPRESSION
mode:CompressionModeZlib
error:error];
} // gtm_dataByDeflatingData:
+ (NSData *)gtm_dataByDeflatingBytes:(const void *)bytes
length:(NSUInteger)length
compressionLevel:(int)level {
return [self gtm_dataByDeflatingBytes:bytes
length:length
compressionLevel:level
error:NULL];
} // gtm_dataByDeflatingBytes:length:level:
+ (NSData *)gtm_dataByDeflatingBytes:(const void *)bytes
length:(NSUInteger)length
compressionLevel:(int)level
error:(NSError **)error {
return [self gtm_dataByCompressingBytes:bytes
length:length
compressionLevel:level
mode:CompressionModeZlib
error:error];
} // gtm_dataByDeflatingBytes:length:level:error:
+ (NSData *)gtm_dataByDeflatingData:(NSData *)data
compressionLevel:(int)level {
return [self gtm_dataByDeflatingData:data
compressionLevel:level
error:NULL];
} // gtm_dataByDeflatingData:level:
+ (NSData *)gtm_dataByDeflatingData:(NSData *)data
compressionLevel:(int)level
error:(NSError **)error {
return [self gtm_dataByCompressingBytes:[data bytes]
length:[data length]
compressionLevel:level
mode:CompressionModeZlib
error:error];
} // gtm_dataByDeflatingData:level:error:
#pragma mark -
+ (NSData *)gtm_dataByInflatingBytes:(const void *)bytes
length:(NSUInteger)length {
return [self gtm_dataByInflatingBytes:bytes
length:length
error:NULL];
} // gtm_dataByInflatingBytes:length:
+ (NSData *)gtm_dataByInflatingBytes:(const void *)bytes
length:(NSUInteger)length
error:(NSError **)error {
return [self gtm_dataByInflatingBytes:bytes
length:length
isRawData:NO
error:error];
} // gtm_dataByInflatingBytes:length:error:
+ (NSData *)gtm_dataByInflatingData:(NSData *)data {
return [self gtm_dataByInflatingData:data error:NULL];
} // gtm_dataByInflatingData:
+ (NSData *)gtm_dataByInflatingData:(NSData *)data
error:(NSError **)error {
return [self gtm_dataByInflatingBytes:[data bytes]
length:[data length]
isRawData:NO
error:error];
} // gtm_dataByInflatingData:
#pragma mark -
+ (NSData *)gtm_dataByRawDeflatingBytes:(const void *)bytes
length:(NSUInteger)length {
return [self gtm_dataByRawDeflatingBytes:(const void *)bytes
length:(NSUInteger)length
error:NULL];
} // gtm_dataByRawDeflatingBytes:length:
+ (NSData *)gtm_dataByRawDeflatingBytes:(const void *)bytes
length:(NSUInteger)length
error:(NSError **)error {
return [self gtm_dataByCompressingBytes:bytes
length:length
compressionLevel:Z_DEFAULT_COMPRESSION
mode:CompressionModeRaw
error:error];
} // gtm_dataByRawDeflatingBytes:length:error:
+ (NSData *)gtm_dataByRawDeflatingData:(NSData *)data {
return [self gtm_dataByRawDeflatingData:data error:NULL];
} // gtm_dataByRawDeflatingData:
+ (NSData *)gtm_dataByRawDeflatingData:(NSData *)data error:(NSError **)error {
return [self gtm_dataByCompressingBytes:[data bytes]
length:[data length]
compressionLevel:Z_DEFAULT_COMPRESSION
mode:CompressionModeRaw
error:error];
} // gtm_dataByRawDeflatingData:error:
+ (NSData *)gtm_dataByRawDeflatingBytes:(const void *)bytes
length:(NSUInteger)length
compressionLevel:(int)level {
return [self gtm_dataByRawDeflatingBytes:bytes
length:length
compressionLevel:level
error:NULL];
} // gtm_dataByRawDeflatingBytes:length:compressionLevel:
+ (NSData *)gtm_dataByRawDeflatingBytes:(const void *)bytes
length:(NSUInteger)length
compressionLevel:(int)level
error:(NSError **)error{
return [self gtm_dataByCompressingBytes:bytes
length:length
compressionLevel:level
mode:CompressionModeRaw
error:error];
} // gtm_dataByRawDeflatingBytes:length:compressionLevel:error:
+ (NSData *)gtm_dataByRawDeflatingData:(NSData *)data
compressionLevel:(int)level {
return [self gtm_dataByRawDeflatingData:data
compressionLevel:level
error:NULL];
} // gtm_dataByRawDeflatingData:compressionLevel:
+ (NSData *)gtm_dataByRawDeflatingData:(NSData *)data
compressionLevel:(int)level
error:(NSError **)error {
return [self gtm_dataByCompressingBytes:[data bytes]
length:[data length]
compressionLevel:level
mode:CompressionModeRaw
error:error];
} // gtm_dataByRawDeflatingData:compressionLevel:error:
+ (NSData *)gtm_dataByRawInflatingBytes:(const void *)bytes
length:(NSUInteger)length {
return [self gtm_dataByInflatingBytes:bytes
length:length
error:NULL];
} // gtm_dataByRawInflatingBytes:length:
+ (NSData *)gtm_dataByRawInflatingBytes:(const void *)bytes
length:(NSUInteger)length
error:(NSError **)error{
return [self gtm_dataByInflatingBytes:bytes
length:length
isRawData:YES
error:error];
} // gtm_dataByRawInflatingBytes:length:error:
+ (NSData *)gtm_dataByRawInflatingData:(NSData *)data {
return [self gtm_dataByRawInflatingData:data
error:NULL];
} // gtm_dataByRawInflatingData:
+ (NSData *)gtm_dataByRawInflatingData:(NSData *)data
error:(NSError **)error {
return [self gtm_dataByInflatingBytes:[data bytes]
length:[data length]
isRawData:YES
error:error];
} // gtm_dataByRawInflatingData:error:
@end

View File

@@ -0,0 +1,40 @@
//
// GTMNSDictionary+URLArguments.h
//
// Copyright 2006-2008 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not
// use this file except in compliance with the License. You may obtain a copy
// of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations under
// the License.
//
#import <Foundation/Foundation.h>
/// Utility for building a URL or POST argument string.
@interface NSDictionary (GTMNSDictionaryURLArgumentsAdditions)
/// Returns a dictionary of the decoded key-value pairs in a http arguments
/// string of the form key1=value1&key2=value2&...&keyN=valueN.
/// Keys and values will be unescaped automatically.
/// Only the first value for a repeated key is returned.
///
/// NOTE: Apps targeting iOS 8 or OS X 10.10 and later should use
/// NSURLComponents and NSURLQueryItem to create URLs with
/// query arguments instead of using these category methods.
+ (NSDictionary *)gtm_dictionaryWithHttpArgumentsString:(NSString *)argString;
/// Gets a string representation of the dictionary in the form
/// key1=value1&key2=value2&...&keyN=valueN, suitable for use as either
/// URL arguments (after a '?') or POST body. Keys and values will be escaped
/// automatically, so should be unescaped in the dictionary.
- (NSString *)gtm_httpArgumentsString;
@end

View File

@@ -0,0 +1,77 @@
//
// GTMNSDictionary+URLArguments.m
//
// Copyright 2006-2008 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not
// use this file except in compliance with the License. You may obtain a copy
// of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations under
// the License.
//
#import "GTMNSDictionary+URLArguments.h"
#import "GTMNSString+URLArguments.h"
#import "GTMMethodCheck.h"
#import "GTMDefines.h"
// Export a nonsense symbol to suppress a libtool warning when this is linked alone in a static lib.
__attribute__((visibility("default")))
char GTMNSDictionaryURLArgumentsExportToSuppressLibToolWarning = 0;
@implementation NSDictionary (GTMNSDictionaryURLArgumentsAdditions)
GTM_METHOD_CHECK(NSString, gtm_stringByEscapingForURLArgument);
GTM_METHOD_CHECK(NSString, gtm_stringByUnescapingFromURLArgument);
+ (NSDictionary *)gtm_dictionaryWithHttpArgumentsString:(NSString *)argString {
NSMutableDictionary* ret = [NSMutableDictionary dictionary];
NSArray* components = [argString componentsSeparatedByString:@"&"];
NSString* component;
// Use reverse order so that the first occurrence of a key replaces
// those subsequent.
for (component in [components reverseObjectEnumerator]) {
if ([component length] == 0)
continue;
NSRange pos = [component rangeOfString:@"="];
NSString *key;
NSString *val;
if (pos.location == NSNotFound) {
key = [component gtm_stringByUnescapingFromURLArgument];
val = @"";
} else {
key = [[component substringToIndex:pos.location]
gtm_stringByUnescapingFromURLArgument];
val = [[component substringFromIndex:pos.location + pos.length]
gtm_stringByUnescapingFromURLArgument];
}
// gtm_stringByUnescapingFromURLArgument returns nil on invalid UTF8
// and NSMutableDictionary raises an exception when passed nil values.
if (!key) key = @"";
if (!val) val = @"";
[ret setObject:val forKey:key];
}
return ret;
}
- (NSString *)gtm_httpArgumentsString {
NSMutableArray* arguments = [NSMutableArray arrayWithCapacity:[self count]];
NSString* key;
for (key in self) {
[arguments addObject:[NSString stringWithFormat:@"%@=%@",
[key gtm_stringByEscapingForURLArgument],
[[[self objectForKey:key] description] gtm_stringByEscapingForURLArgument]]];
}
return [arguments componentsJoinedByString:@"&"];
}
@end

View File

@@ -0,0 +1,45 @@
//
// GTMNSString+URLArguments.h
//
// Copyright 2006-2008 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not
// use this file except in compliance with the License. You may obtain a copy
// of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations under
// the License.
//
#import <Foundation/Foundation.h>
/// Utilities for encoding and decoding URL arguments.
@interface NSString (GTMNSStringURLArgumentsAdditions)
/// Returns a string that is escaped properly to be a URL argument.
///
/// This differs from stringByAddingPercentEscapesUsingEncoding: in that it
/// will escape all the reserved characters (per RFC 3986
/// <http://www.ietf.org/rfc/rfc3986.txt>) which
/// stringByAddingPercentEscapesUsingEncoding would leave.
///
/// This will also escape '%', so this should not be used on a string that has
/// already been escaped unless double-escaping is the desired result.
///
/// NOTE: Apps targeting iOS 8 or OS X 10.10 and later should use
/// NSURLComponents and NSURLQueryItem to create properly-escaped
/// URLs instead of using these category methods.
- (NSString*)gtm_stringByEscapingForURLArgument;
/// Returns the unescaped version of a URL argument
///
/// This has the same behavior as stringByReplacingPercentEscapesUsingEncoding:,
/// except that it will also convert '+' to space.
- (NSString*)gtm_stringByUnescapingFromURLArgument;
@end

View File

@@ -0,0 +1,48 @@
//
// GTMNSString+URLArguments.m
//
// Copyright 2006-2008 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not
// use this file except in compliance with the License. You may obtain a copy
// of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations under
// the License.
//
#import "GTMNSString+URLArguments.h"
@implementation NSString (GTMNSStringURLArgumentsAdditions)
- (NSString *)gtm_stringByEscapingForURLArgument {
// Encode all the reserved characters, per RFC 3986
// (<http://www.ietf.org/rfc/rfc3986.txt>)
CFStringRef escaped =
CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault,
(CFStringRef)self,
NULL,
(CFStringRef)@"!*'();:@&=+$,/?%#[]",
kCFStringEncodingUTF8);
#if defined(__has_feature) && __has_feature(objc_arc)
return CFBridgingRelease(escaped);
#else
return [(NSString *)escaped autorelease];
#endif
}
- (NSString *)gtm_stringByUnescapingFromURLArgument {
NSMutableString *resultString = [NSMutableString stringWithString:self];
[resultString replaceOccurrencesOfString:@"+"
withString:@" "
options:NSLiteralSearch
range:NSMakeRange(0, [resultString length])];
return [resultString stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
}
@end

View File

@@ -0,0 +1,392 @@
//
// GTMDefines.h
//
// Copyright 2008 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not
// use this file except in compliance with the License. You may obtain a copy
// of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations under
// the License.
//
// ============================================================================
#include <AvailabilityMacros.h>
#include <TargetConditionals.h>
#ifdef __OBJC__
#include <Foundation/NSObjCRuntime.h>
#endif // __OBJC__
#if TARGET_OS_IPHONE
#include <Availability.h>
#endif // TARGET_OS_IPHONE
// ----------------------------------------------------------------------------
// CPP symbols that can be overridden in a prefix to control how the toolbox
// is compiled.
// ----------------------------------------------------------------------------
// By setting the GTM_CONTAINERS_VALIDATION_FAILED_LOG and
// GTM_CONTAINERS_VALIDATION_FAILED_ASSERT macros you can control what happens
// when a validation fails. If you implement your own validators, you may want
// to control their internals using the same macros for consistency.
#ifndef GTM_CONTAINERS_VALIDATION_FAILED_ASSERT
#define GTM_CONTAINERS_VALIDATION_FAILED_ASSERT 0
#endif
// Ensure __has_feature and __has_extension are safe to use.
// See http://clang-analyzer.llvm.org/annotations.html
#ifndef __has_feature // Optional.
#define __has_feature(x) 0 // Compatibility with non-clang compilers.
#endif
#ifndef __has_extension
#define __has_extension __has_feature // Compatibility with pre-3.0 compilers.
#endif
// Give ourselves a consistent way to do inlines. Apple's macros even use
// a few different actual definitions, so we're based off of the foundation
// one.
#if !defined(GTM_INLINE)
#if (defined (__GNUC__) && (__GNUC__ == 4)) || defined (__clang__)
#define GTM_INLINE static __inline__ __attribute__((always_inline))
#else
#define GTM_INLINE static __inline__
#endif
#endif
// Give ourselves a consistent way of doing externs that links up nicely
// when mixing objc and objc++
#if !defined (GTM_EXTERN)
#if defined __cplusplus
#define GTM_EXTERN extern "C"
#define GTM_EXTERN_C_BEGIN extern "C" {
#define GTM_EXTERN_C_END }
#else
#define GTM_EXTERN extern
#define GTM_EXTERN_C_BEGIN
#define GTM_EXTERN_C_END
#endif
#endif
// Give ourselves a consistent way of exporting things if we have visibility
// set to hidden.
#if !defined (GTM_EXPORT)
#define GTM_EXPORT __attribute__((visibility("default")))
#endif
// Give ourselves a consistent way of declaring something as unused. This
// doesn't use __unused because that is only supported in gcc 4.2 and greater.
#if !defined (GTM_UNUSED)
#define GTM_UNUSED(x) ((void)(x))
#endif
// _GTMDevLog & _GTMDevAssert
//
// _GTMDevLog & _GTMDevAssert are meant to be a very lightweight shell for
// developer level errors. This implementation simply macros to NSLog/NSAssert.
// It is not intended to be a general logging/reporting system.
//
// Please see http://code.google.com/p/google-toolbox-for-mac/wiki/DevLogNAssert
// for a little more background on the usage of these macros.
//
// _GTMDevLog log some error/problem in debug builds
// _GTMDevAssert assert if condition isn't met w/in a method/function
// in all builds.
//
// To replace this system, just provide different macro definitions in your
// prefix header. Remember, any implementation you provide *must* be thread
// safe since this could be called by anything in what ever situtation it has
// been placed in.
//
// We only define the simple macros if nothing else has defined this.
#ifndef _GTMDevLog
#ifdef DEBUG
#define _GTMDevLog(...) NSLog(__VA_ARGS__)
#else
#define _GTMDevLog(...) do { } while (0)
#endif
#endif // _GTMDevLog
#ifndef _GTMDevAssert
// we directly invoke the NSAssert handler so we can pass on the varargs
// (NSAssert doesn't have a macro we can use that takes varargs)
#if !defined(NS_BLOCK_ASSERTIONS)
#define _GTMDevAssert(condition, ...) \
do { \
if (!(condition)) { \
[[NSAssertionHandler currentHandler] \
handleFailureInFunction:(NSString *) \
[NSString stringWithUTF8String:__PRETTY_FUNCTION__] \
file:(NSString *)[NSString stringWithUTF8String:__FILE__] \
lineNumber:__LINE__ \
description:__VA_ARGS__]; \
} \
} while(0)
#else // !defined(NS_BLOCK_ASSERTIONS)
#define _GTMDevAssert(condition, ...) do { } while (0)
#endif // !defined(NS_BLOCK_ASSERTIONS)
#endif // _GTMDevAssert
// _GTMCompileAssert
//
// Note: Software for current compilers should just use _Static_assert directly
// instead of this macro.
//
// _GTMCompileAssert is an assert that is meant to fire at compile time if you
// want to check things at compile instead of runtime. For example if you
// want to check that a wchar is 4 bytes instead of 2 you would use
// _GTMCompileAssert(sizeof(wchar_t) == 4, wchar_t_is_4_bytes_on_OS_X)
// Note that the second "arg" is not in quotes, and must be a valid processor
// symbol in it's own right (no spaces, punctuation etc).
// Wrapping this in an #ifndef allows external groups to define their own
// compile time assert scheme.
#ifndef _GTMCompileAssert
#if __has_feature(c_static_assert) || __has_extension(c_static_assert)
#define _GTMCompileAssert(test, msg) _Static_assert((test), #msg)
#else
// Pre-Xcode 7 support.
//
// We got this technique from here:
// http://unixjunkie.blogspot.com/2007/10/better-compile-time-asserts_29.html
#define _GTMCompileAssertSymbolInner(line, msg) _GTMCOMPILEASSERT ## line ## __ ## msg
#define _GTMCompileAssertSymbol(line, msg) _GTMCompileAssertSymbolInner(line, msg)
#define _GTMCompileAssert(test, msg) \
typedef char _GTMCompileAssertSymbol(__LINE__, msg) [ ((test) ? 1 : -1) ]
#endif // __has_feature(c_static_assert) || __has_extension(c_static_assert)
#endif // _GTMCompileAssert
// ----------------------------------------------------------------------------
// CPP symbols defined based on the project settings so the GTM code has
// simple things to test against w/o scattering the knowledge of project
// setting through all the code.
// ----------------------------------------------------------------------------
// Provide a single constant CPP symbol that all of GTM uses for ifdefing
// iPhone code.
#if TARGET_OS_IPHONE // iPhone SDK
// For iPhone specific stuff
#define GTM_IPHONE_SDK 1
#if TARGET_IPHONE_SIMULATOR
#define GTM_IPHONE_DEVICE 0
#define GTM_IPHONE_SIMULATOR 1
#else
#define GTM_IPHONE_DEVICE 1
#define GTM_IPHONE_SIMULATOR 0
#endif // TARGET_IPHONE_SIMULATOR
// By default, GTM has provided it's own unittesting support, define this
// to use the support provided by Xcode, especially for the Xcode4 support
// for unittesting.
#ifndef GTM_USING_XCTEST
#define GTM_USING_XCTEST 0
#endif
#define GTM_MACOS_SDK 0
#else
// For MacOS specific stuff
#define GTM_MACOS_SDK 1
#define GTM_IPHONE_SDK 0
#define GTM_IPHONE_SIMULATOR 0
#define GTM_IPHONE_DEVICE 0
#ifndef GTM_USING_XCTEST
#define GTM_USING_XCTEST 0
#endif
#endif
// Some of our own availability macros
#if GTM_MACOS_SDK
#define GTM_AVAILABLE_ONLY_ON_IPHONE UNAVAILABLE_ATTRIBUTE
#define GTM_AVAILABLE_ONLY_ON_MACOS
#else
#define GTM_AVAILABLE_ONLY_ON_IPHONE
#define GTM_AVAILABLE_ONLY_ON_MACOS UNAVAILABLE_ATTRIBUTE
#endif
// GC was dropped by Apple, define the old constant incase anyone still keys
// off of it.
#ifndef GTM_SUPPORT_GC
#define GTM_SUPPORT_GC 0
#endif
// Some support for advanced clang static analysis functionality
#ifndef NS_RETURNS_RETAINED
#if __has_feature(attribute_ns_returns_retained)
#define NS_RETURNS_RETAINED __attribute__((ns_returns_retained))
#else
#define NS_RETURNS_RETAINED
#endif
#endif
#ifndef NS_RETURNS_NOT_RETAINED
#if __has_feature(attribute_ns_returns_not_retained)
#define NS_RETURNS_NOT_RETAINED __attribute__((ns_returns_not_retained))
#else
#define NS_RETURNS_NOT_RETAINED
#endif
#endif
#ifndef CF_RETURNS_RETAINED
#if __has_feature(attribute_cf_returns_retained)
#define CF_RETURNS_RETAINED __attribute__((cf_returns_retained))
#else
#define CF_RETURNS_RETAINED
#endif
#endif
#ifndef CF_RETURNS_NOT_RETAINED
#if __has_feature(attribute_cf_returns_not_retained)
#define CF_RETURNS_NOT_RETAINED __attribute__((cf_returns_not_retained))
#else
#define CF_RETURNS_NOT_RETAINED
#endif
#endif
#ifndef NS_CONSUMED
#if __has_feature(attribute_ns_consumed)
#define NS_CONSUMED __attribute__((ns_consumed))
#else
#define NS_CONSUMED
#endif
#endif
#ifndef CF_CONSUMED
#if __has_feature(attribute_cf_consumed)
#define CF_CONSUMED __attribute__((cf_consumed))
#else
#define CF_CONSUMED
#endif
#endif
#ifndef NS_CONSUMES_SELF
#if __has_feature(attribute_ns_consumes_self)
#define NS_CONSUMES_SELF __attribute__((ns_consumes_self))
#else
#define NS_CONSUMES_SELF
#endif
#endif
#ifndef GTM_NONNULL
#if defined(__has_attribute)
#if __has_attribute(nonnull)
#define GTM_NONNULL(x) __attribute__((nonnull x))
#else
#define GTM_NONNULL(x)
#endif
#else
#define GTM_NONNULL(x)
#endif
#endif
// Invalidates the initializer from which it's called.
#ifndef GTMInvalidateInitializer
#if __has_feature(objc_arc)
#define GTMInvalidateInitializer() \
do { \
[self class]; /* Avoid warning of dead store to |self|. */ \
_GTMDevAssert(NO, @"Invalid initializer."); \
return nil; \
} while (0)
#else
#define GTMInvalidateInitializer() \
do { \
[self release]; \
_GTMDevAssert(NO, @"Invalid initializer."); \
return nil; \
} while (0)
#endif
#endif
#ifndef GTMCFAutorelease
// GTMCFAutorelease returns an id. In contrast, Apple's CFAutorelease returns
// a CFTypeRef.
#if __has_feature(objc_arc)
#define GTMCFAutorelease(x) CFBridgingRelease(x)
#else
#define GTMCFAutorelease(x) ([(id)x autorelease])
#endif
#endif
#ifdef __OBJC__
// Macro to allow you to create NSStrings out of other macros.
// #define FOO foo
// NSString *fooString = GTM_NSSTRINGIFY(FOO);
#if !defined (GTM_NSSTRINGIFY)
#define GTM_NSSTRINGIFY_INNER(x) @#x
#define GTM_NSSTRINGIFY(x) GTM_NSSTRINGIFY_INNER(x)
#endif
// Macro to allow fast enumeration when building for 10.5 or later, and
// reliance on NSEnumerator for 10.4. Remember, NSDictionary w/ FastEnumeration
// does keys, so pick the right thing, nothing is done on the FastEnumeration
// side to be sure you're getting what you wanted.
#ifndef GTM_FOREACH_OBJECT
#if TARGET_OS_IPHONE || !(MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5)
#define GTM_FOREACH_ENUMEREE(element, enumeration) \
for (element in enumeration)
#define GTM_FOREACH_OBJECT(element, collection) \
for (element in collection)
#define GTM_FOREACH_KEY(element, collection) \
for (element in collection)
#else
#define GTM_FOREACH_ENUMEREE(element, enumeration) \
for (NSEnumerator *_ ## element ## _enum = enumeration; \
(element = [_ ## element ## _enum nextObject]) != nil; )
#define GTM_FOREACH_OBJECT(element, collection) \
GTM_FOREACH_ENUMEREE(element, [collection objectEnumerator])
#define GTM_FOREACH_KEY(element, collection) \
GTM_FOREACH_ENUMEREE(element, [collection keyEnumerator])
#endif
#endif
// ============================================================================
// GTM_SEL_STRING is for specifying selector (usually property) names to KVC
// or KVO methods.
// In debug it will generate warnings for undeclared selectors if
// -Wunknown-selector is turned on.
// In release it will have no runtime overhead.
#ifndef GTM_SEL_STRING
#ifdef DEBUG
#define GTM_SEL_STRING(selName) NSStringFromSelector(@selector(selName))
#else
#define GTM_SEL_STRING(selName) @#selName
#endif // DEBUG
#endif // GTM_SEL_STRING
#ifndef GTM_WEAK
#if __has_feature(objc_arc_weak)
// With ARC enabled, __weak means a reference that isn't implicitly
// retained. __weak objects are accessed through runtime functions, so
// they are zeroed out, but this requires OS X 10.7+.
// At clang r251041+, ARC-style zeroing weak references even work in
// non-ARC mode.
#define GTM_WEAK __weak
#elif __has_feature(objc_arc)
// ARC, but targeting 10.6 or older, where zeroing weak references don't
// exist.
#define GTM_WEAK __unsafe_unretained
#else
// With manual reference counting, __weak used to be silently ignored.
// clang r251041 gives it the ARC semantics instead. This means they
// now require a deployment target of 10.7, while some clients of GTM
// still target 10.6. In these cases, expand to __unsafe_unretained instead
#define GTM_WEAK
#endif
#endif
#endif // __OBJC__

View File

@@ -0,0 +1,202 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

View File

@@ -0,0 +1,15 @@
# GTM: Google Toolbox for Mac #
**Project site** <https://github.com/google/google-toolbox-for-mac><br>
**Discussion group** <http://groups.google.com/group/google-toolbox-for-mac>
# Google Toolbox for Mac #
A collection of source from different Google projects that may be of use to
developers working other iOS or OS X projects.
If you find a problem/bug or want a new feature to be included in the Google
Toolbox for Mac, please join the
[discussion group](http://groups.google.com/group/google-toolbox-for-mac)
or submit an
[issue](https://github.com/google/google-toolbox-for-mac/issues).