Martijn The avatar Martijn The committed cebc51e

Real initial commit :-)

Comments (0)

Files changed (14)

+[submodule "NSURLConnectionVCRTests/CocoaHTTPServer"]
+	path = NSURLConnectionVCRTests/CocoaHTTPServer
+	url = https://github.com/robbiehanson/CocoaHTTPServer.git

NSURLConnectionVCR/NSURLConnectionVCR.h

 //
 //  NSURLConnectionVCR.h
-//  NSURLConnectionVCR
 //
-//  Created by Martijn Thé on 2/25/12.
-//  Copyright (c) 2012 __MyCompanyName__. All rights reserved.
+//  Created by Martijn Thé on 19-02-12.
+//  Copyright (c) 2012 martijnthe.nl All rights reserved.
 //
 
 #import <Foundation/Foundation.h>
 
-@interface NSURLConnectionVCR : NSObject
+/**
+ *  NSURLConnectionVCR provides a way to re-play NSURLConnection HTTP responses.
+ *  It is inspired on Ruby's VCR.
+ */
+
+extern NSString* NSURLConnectionVCRErrorDomain;
 
+enum NSURLConnectionVCRErrorCodes {
+    NSURLConnectionVCRErrorAlreadyStarted,
+    NSURLConnectionVCRErrorAlreadyStopped
+};
+
+@interface NSURLConnectionVCR : NSObject
++ (BOOL)startVCRWithPath:(NSString*)path error:(NSError**)error;
++ (BOOL)stopVCRWithError:(NSError**)error;
++ (BOOL)isVCRStarted;
 @end

NSURLConnectionVCR/NSURLConnectionVCR.m

-//
-//  NSURLConnectionVCR.m
-//  NSURLConnectionVCR
-//
-//  Created by Martijn Thé on 2/25/12.
-//  Copyright (c) 2012 __MyCompanyName__. All rights reserved.
-//
-
-#import "NSURLConnectionVCR.h"
-
-@implementation NSURLConnectionVCR
-
-@end

NSURLConnectionVCR/NSURLConnectionVCR.mm

+//
+//  NSURLConnectionVCR.m
+//
+//  Created by Martijn Thé on 19-02-12.
+//  Copyright (c) 2012 martijnthe.nl All rights reserved.
+//
+
+#import "NSURLConnectionVCR.h"
+#import "SKUtils.h"
+#import <CommonCrypto/CommonDigest.h>
+#import <objc/runtime.h>
+ 
+NSString* NSURLConnectionVCRErrorDomain = @"NSURLConnectionVCRErrorDomain";
+struct objc_class;
+__strong static NSString* casettesPath;
+
+
+@interface VCRCache : NSObject <NSCoding>
+@property (nonatomic, readwrite, strong) NSURLResponse* response;
+@property (nonatomic, readwrite, strong) NSData* responseBody;
++ (VCRCache*)loadCacheForRequest:(NSURLRequest*)request;
++ (BOOL)storeResponse:(NSURLResponse*)response withResponseBody:(NSData*)data forRequest:(NSURLRequest*)request;
+@end
+
+
+@interface NSURLConnectionVCR ()
+@property (nonatomic, retain, readwrite) NSURLConnection* origConnection;
+@end
+
+
+@implementation NSURLConnectionVCR {
+    NSURLConnection* origConnection;
+}
+@synthesize origConnection;
+
+static IMP allocImplementationOrig = NULL;
+static id VCRAllocImplementation(id theSelf, SEL cmd, ...) {
+    NSURLConnectionVCR* vcr = [NSURLConnectionVCR alloc];
+    // Call original +alloc method:
+    NSURLConnection* origConn = allocImplementationOrig(theSelf, cmd);
+    [vcr setOrigConnection:origConn];
+    return vcr;
+}
+
++ (BOOL)startVCRWithPath:(NSString*)path error:(NSError *__autoreleasing *)error {
+    if ([self isVCRStarted]) {
+        if (error) {
+            *error = [NSError errorWithDomain:NSURLConnectionVCRErrorDomain code:NSURLConnectionVCRErrorAlreadyStarted userInfo:nil];
+        }
+        return NO;
+    } else {
+        Class connectionClass = NSClassFromString(@"NSURLConnection");
+        Class connectionMetaClass = objc_getMetaClass("NSURLConnection");
+        Method origMethod = class_getClassMethod(connectionClass, @selector(alloc));
+        allocImplementationOrig = method_getImplementation(origMethod);
+        class_replaceMethod(connectionMetaClass, @selector(alloc), VCRAllocImplementation, "@@:");        
+        
+        casettesPath = path;
+        
+        return YES;
+    }
+}
+
++ (BOOL)stopVCRWithError:(NSError**)error {
+    if ([self isVCRStarted] == NO) {
+        if (error) {
+            *error = [NSError errorWithDomain:NSURLConnectionVCRErrorDomain code:NSURLConnectionVCRErrorAlreadyStopped userInfo:nil];
+        }
+        return NO;
+    } else {
+        Class connectionMetaClass = objc_getMetaClass("NSURLConnection");
+        class_replaceMethod(connectionMetaClass, @selector(alloc), allocImplementationOrig, "@@:");        
+        allocImplementationOrig = NULL;
+        
+        casettesPath = nil;
+        
+        return YES;
+    }
+}
+
++ (BOOL)isVCRStarted {
+    return (allocImplementationOrig != NULL);
+}
+
+- (BOOL)respondsToSelector:(SEL)aSelector {
+    return [origConnection respondsToSelector:aSelector];
+}
+
+- (void)doesNotRecognizeSelector:(SEL)aSelector {
+    
+}
+
+- (id)forwardingTargetForSelector:(SEL)aSelector {
+    return origConnection;
+}
+
+- (void)forwardInvocation:(NSInvocation *)anInvocation {
+    
+}
+
+@end
+
+
+@interface VCRCache (Private)
++ (NSString*)hashForRequest:(NSURLRequest*)request;
++ (NSString*)filePathForRequest:(NSURLRequest*)request;
+@end
+
+
+@implementation VCRCache
+@synthesize response;
+@synthesize responseBody;
+
++ (VCRCache*)loadCacheForRequest:(NSURLRequest*)request {
+    VCRCache* cache = [NSKeyedUnarchiver unarchiveObjectWithFile:[self filePathForRequest:request]];
+    return cache;
+}
+
++ (BOOL)storeResponse:(NSURLResponse*)response withResponseBody:(NSData*)data forRequest:(NSURLRequest*)request {
+    VCRCache* cache = [[VCRCache alloc] init];
+    cache.response = response;
+    cache.responseBody = data;
+    return [NSKeyedArchiver archiveRootObject:cache toFile:[self filePathForRequest:request]];
+}
+
+- (id)initWithCoder:(NSCoder *)coder {
+    if (self) {
+        self.response = [coder decodeObjectForKey:@"response"];
+        self.responseBody = [coder decodeObjectForKey:@"responseBody"];
+    }
+    return self;
+}
+
+- (void)encodeWithCoder:(NSCoder *)aCoder {
+    [aCoder encodeObject:response forKey:@"response"];
+    [aCoder encodeObject:responseBody forKey:@"responseBody"];
+}
+
+@end
+
+
+@implementation VCRCache (Private)
+
++ (NSString*)hashForRequest:(NSURLRequest*)request {
+    NSData* data = [NSKeyedArchiver archivedDataWithRootObject:request];
+    unsigned char md5[CC_MD5_DIGEST_LENGTH];
+    CC_MD5([data bytes], (CC_LONG)[data length], md5);
+    NSString* md5String = (__bridge_transfer NSString*)SKUtilsCreateStringHexadecimalRepresentationOfBytes(md5, CC_MD5_DIGEST_LENGTH);
+    return md5String;
+}
+
++ (NSString*)filePathForRequest:(NSURLRequest*)request {
+    NSString* filePath = [casettesPath stringByAppendingPathComponent:[self hashForRequest:request]];
+    return filePath;
+}
+
+@end

NSURLConnectionVCR/SKUtils.h

+//
+//  SKUtils.h
+//  Keychain+
+//
+//  Created by Martijn Thé on 08-01-12.
+//  Copyright (c) 2012 Martijn Thé. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+
+CFStringRef SKUtilsCreateStringHexadecimalRepresentationOfBytes(const UInt8* bytes, CFIndex length);

NSURLConnectionVCR/SKUtils.mm

+//
+//  SKUtils.m
+//  Keychain+
+//
+//  Created by Martijn Thé on 08-01-12.
+//  Copyright (c) 2012 Martijn Thé. All rights reserved.
+//
+
+#import "SKUtils.h"
+
+CFStringRef SKUtilsCreateStringHexadecimalRepresentationOfBytes(const UInt8* bytes, CFIndex length) {
+    UInt8 hexMap[] = "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F808182838485868788898A8B8C8D8E8F909192939495969798999A9B9C9D9E9FA0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBFC0C1C2C3C4C5C6C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6D7D8D9DADBDCDDDEDFE0E1E2E3E4E5E6E7E8E9EAEBECEDEEEFF0F1F2F3F4F5F6F7F8F9FAFBFCFDFEFF";
+    
+    UInt8 *c = (UInt8 *)malloc(length * 2);
+    UInt16 *ptr = (UInt16*) c;
+    UInt16 *last = (UInt16*) (c + (length * 2));
+    for (;;) {
+        *ptr = ((UInt16*)hexMap)[*bytes];
+        ++ptr;
+        ++bytes;
+        if (ptr == last) {
+            return (__bridge_retained CFStringRef)[[NSString alloc] initWithBytesNoCopy:c length:length * 2 encoding:NSUTF8StringEncoding freeWhenDone:NO];
+            
+            // Not implemented in Cocotron:
+//            return CFStringCreateWithBytesNoCopy(NULL, c, length * 2, kCFStringEncodingUTF8, false, kCFAllocatorMalloc);
+        }
+    }
+}

NSURLConnectionVCRQuicklook/GeneratePreviewForURL.m

+#include <CoreFoundation/CoreFoundation.h>
+#include <CoreServices/CoreServices.h>
+#include <QuickLook/QuickLook.h>
+
+OSStatus GeneratePreviewForURL(void *thisInterface, QLPreviewRequestRef preview, CFURLRef url, CFStringRef contentTypeUTI, CFDictionaryRef options);
+void CancelPreviewGeneration(void *thisInterface, QLPreviewRequestRef preview);
+
+/* -----------------------------------------------------------------------------
+   Generate a preview for file
+
+   This function's job is to create preview for designated file
+   ----------------------------------------------------------------------------- */
+
+OSStatus GeneratePreviewForURL(void *thisInterface, QLPreviewRequestRef preview, CFURLRef url, CFStringRef contentTypeUTI, CFDictionaryRef options)
+{
+    // To complete your generator please implement the function GeneratePreviewForURL in GeneratePreviewForURL.c
+    return noErr;
+}
+
+void CancelPreviewGeneration(void *thisInterface, QLPreviewRequestRef preview)
+{
+    // Implement only if supported
+}

NSURLConnectionVCRQuicklook/GenerateThumbnailForURL.m

+#include <CoreFoundation/CoreFoundation.h>
+#include <CoreServices/CoreServices.h>
+#include <QuickLook/QuickLook.h>
+
+OSStatus GenerateThumbnailForURL(void *thisInterface, QLThumbnailRequestRef thumbnail, CFURLRef url, CFStringRef contentTypeUTI, CFDictionaryRef options, CGSize maxSize);
+void CancelThumbnailGeneration(void *thisInterface, QLThumbnailRequestRef thumbnail);
+
+/* -----------------------------------------------------------------------------
+    Generate a thumbnail for file
+
+   This function's job is to create thumbnail for designated file as fast as possible
+   ----------------------------------------------------------------------------- */
+
+OSStatus GenerateThumbnailForURL(void *thisInterface, QLThumbnailRequestRef thumbnail, CFURLRef url, CFStringRef contentTypeUTI, CFDictionaryRef options, CGSize maxSize)
+{
+    // To complete your generator please implement the function GenerateThumbnailForURL in GenerateThumbnailForURL.c
+    return noErr;
+}
+
+void CancelThumbnailGeneration(void *thisInterface, QLThumbnailRequestRef thumbnail)
+{
+    // Implement only if supported
+}

NSURLConnectionVCRQuicklook/NSURLConnectionVCRQuicklook-Info.plist

+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>CFBundleDevelopmentRegion</key>
+	<string>English</string>
+	<key>CFBundleDocumentTypes</key>
+	<array>
+		<dict>
+			<key>CFBundleTypeRole</key>
+			<string>QLGenerator</string>
+			<key>LSItemContentTypes</key>
+			<array>
+				<string>SUPPORTED_UTI_TYPE</string>
+			</array>
+		</dict>
+	</array>
+	<key>CFBundleExecutable</key>
+	<string>${EXECUTABLE_NAME}</string>
+	<key>CFBundleIconFile</key>
+	<string></string>
+	<key>CFBundleIdentifier</key>
+	<string>nl.martijnthe.${PRODUCT_NAME:rfc1034identifier}</string>
+	<key>CFBundleInfoDictionaryVersion</key>
+	<string>6.0</string>
+	<key>CFBundleName</key>
+	<string>${PRODUCT_NAME}</string>
+	<key>CFBundleShortVersionString</key>
+	<string>1</string>
+	<key>CFBundleVersion</key>
+	<string>1.0</string>
+	<key>CFPlugInDynamicRegisterFunction</key>
+	<string></string>
+	<key>CFPlugInDynamicRegistration</key>
+	<string>NO</string>
+	<key>CFPlugInFactories</key>
+	<dict>
+		<key>02CC2518-7599-4287-A9DD-1D5664AADC01</key>
+		<string>QuickLookGeneratorPluginFactory</string>
+	</dict>
+	<key>CFPlugInTypes</key>
+	<dict>
+		<key>5E2D9680-5022-40FA-B806-43349622E5B9</key>
+		<array>
+			<string>02CC2518-7599-4287-A9DD-1D5664AADC01</string>
+		</array>
+	</dict>
+	<key>CFPlugInUnloadFunction</key>
+	<string></string>
+	<key>NSHumanReadableCopyright</key>
+	<string>Copyright © 2012 __MyCompanyName__. All rights reserved.</string>
+	<key>QLNeedsToBeRunInMainThread</key>
+	<false/>
+	<key>QLPreviewHeight</key>
+	<real>600</real>
+	<key>QLPreviewWidth</key>
+	<real>800</real>
+	<key>QLSupportsConcurrentRequests</key>
+	<false/>
+	<key>QLThumbnailMinimumSize</key>
+	<real>17</real>
+</dict>
+</plist>

NSURLConnectionVCRQuicklook/NSURLConnectionVCRQuicklook-Prefix.pch

+//
+// Prefix header for all source files of the 'NSURLConnectionVCRQuicklook' target in the 'NSURLConnectionVCRQuicklook' project
+//
+

NSURLConnectionVCRQuicklook/VCRGetPreview.h

+//
+//  VCRGetPreview.h
+//  NSURLConnectionVCR
+//
+//  Created by Martijn Thé on 2/27/12.
+//  Copyright (c) 2012 martijnthe.nl. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+
+@interface VCRGetPreview : NSObject
+
+@end

NSURLConnectionVCRQuicklook/VCRGetPreview.m

+//
+//  VCRGetPreview.m
+//  NSURLConnectionVCR
+//
+//  Created by Martijn Thé on 2/27/12.
+//  Copyright (c) 2012 martijnthe.nl. All rights reserved.
+//
+
+#import "VCRGetPreview.h"
+
+@implementation VCRGetPreview
+
+@end

NSURLConnectionVCRQuicklook/en.lproj/InfoPlist.strings

+/* Localized versions of Info.plist keys */
+

NSURLConnectionVCRQuicklook/main.c

+//==============================================================================
+//
+//	DO NO MODIFY THE CONTENT OF THIS FILE
+//
+//	This file contains the generic CFPlug-in code necessary for your generator
+//	To complete your generator implement the function in GenerateThumbnailForURL/GeneratePreviewForURL.c
+//
+//==============================================================================
+
+
+
+
+
+
+#include <CoreFoundation/CoreFoundation.h>
+#include <CoreFoundation/CFPlugInCOM.h>
+#include <CoreServices/CoreServices.h>
+#include <QuickLook/QuickLook.h>
+
+// -----------------------------------------------------------------------------
+//	constants
+// -----------------------------------------------------------------------------
+
+// Don't modify this line
+#define PLUGIN_ID "02CC2518-7599-4287-A9DD-1D5664AADC01"
+
+//
+// Below is the generic glue code for all plug-ins.
+//
+// You should not have to modify this code aside from changing
+// names if you decide to change the names defined in the Info.plist
+//
+
+
+// -----------------------------------------------------------------------------
+//	typedefs
+// -----------------------------------------------------------------------------
+
+// The thumbnail generation function to be implemented in GenerateThumbnailForURL.c
+OSStatus GenerateThumbnailForURL(void *thisInterface, QLThumbnailRequestRef thumbnail, CFURLRef url, CFStringRef contentTypeUTI, CFDictionaryRef options, CGSize maxSize);
+void CancelThumbnailGeneration(void* thisInterface, QLThumbnailRequestRef thumbnail);
+
+// The preview generation function to be implemented in GeneratePreviewForURL.c
+OSStatus GeneratePreviewForURL(void *thisInterface, QLPreviewRequestRef preview, CFURLRef url, CFStringRef contentTypeUTI, CFDictionaryRef options);
+void CancelPreviewGeneration(void *thisInterface, QLPreviewRequestRef preview);
+
+// The layout for an instance of QuickLookGeneratorPlugIn
+typedef struct __QuickLookGeneratorPluginType
+{
+    void        *conduitInterface;
+    CFUUIDRef    factoryID;
+    UInt32       refCount;
+} QuickLookGeneratorPluginType;
+
+// -----------------------------------------------------------------------------
+//	prototypes
+// -----------------------------------------------------------------------------
+//	Forward declaration for the IUnknown implementation.
+//
+
+QuickLookGeneratorPluginType  *AllocQuickLookGeneratorPluginType(CFUUIDRef inFactoryID);
+void                         DeallocQuickLookGeneratorPluginType(QuickLookGeneratorPluginType *thisInstance);
+HRESULT                      QuickLookGeneratorQueryInterface(void *thisInstance,REFIID iid,LPVOID *ppv);
+void                        *QuickLookGeneratorPluginFactory(CFAllocatorRef allocator,CFUUIDRef typeID);
+ULONG                        QuickLookGeneratorPluginAddRef(void *thisInstance);
+ULONG                        QuickLookGeneratorPluginRelease(void *thisInstance);
+
+// -----------------------------------------------------------------------------
+//	myInterfaceFtbl	definition
+// -----------------------------------------------------------------------------
+//	The QLGeneratorInterfaceStruct function table.
+//
+static QLGeneratorInterfaceStruct myInterfaceFtbl = {
+    NULL,
+    QuickLookGeneratorQueryInterface,
+    QuickLookGeneratorPluginAddRef,
+    QuickLookGeneratorPluginRelease,
+    NULL,
+    NULL,
+    NULL,
+    NULL
+};
+
+
+// -----------------------------------------------------------------------------
+//	AllocQuickLookGeneratorPluginType
+// -----------------------------------------------------------------------------
+//	Utility function that allocates a new instance.
+//      You can do some initial setup for the generator here if you wish
+//      like allocating globals etc...
+//
+QuickLookGeneratorPluginType *AllocQuickLookGeneratorPluginType(CFUUIDRef inFactoryID)
+{
+    QuickLookGeneratorPluginType *theNewInstance;
+
+    theNewInstance = (QuickLookGeneratorPluginType *)malloc(sizeof(QuickLookGeneratorPluginType));
+    memset(theNewInstance,0,sizeof(QuickLookGeneratorPluginType));
+
+        /* Point to the function table Malloc enough to store the stuff and copy the filler from myInterfaceFtbl over */
+    theNewInstance->conduitInterface = malloc(sizeof(QLGeneratorInterfaceStruct));
+    memcpy(theNewInstance->conduitInterface,&myInterfaceFtbl,sizeof(QLGeneratorInterfaceStruct));
+
+        /*  Retain and keep an open instance refcount for each factory. */
+    theNewInstance->factoryID = CFRetain(inFactoryID);
+    CFPlugInAddInstanceForFactory(inFactoryID);
+
+        /* This function returns the IUnknown interface so set the refCount to one. */
+    theNewInstance->refCount = 1;
+    return theNewInstance;
+}
+
+// -----------------------------------------------------------------------------
+//	DeallocQuickLookGeneratorPluginType
+// -----------------------------------------------------------------------------
+//	Utility function that deallocates the instance when
+//	the refCount goes to zero.
+//      In the current implementation generator interfaces are never deallocated
+//      but implement this as this might change in the future
+//
+void DeallocQuickLookGeneratorPluginType(QuickLookGeneratorPluginType *thisInstance)
+{
+    CFUUIDRef theFactoryID;
+
+    theFactoryID = thisInstance->factoryID;
+        /* Free the conduitInterface table up */
+    free(thisInstance->conduitInterface);
+
+        /* Free the instance structure */
+    free(thisInstance);
+    if (theFactoryID){
+        CFPlugInRemoveInstanceForFactory(theFactoryID);
+        CFRelease(theFactoryID);
+    }
+}
+
+// -----------------------------------------------------------------------------
+//	QuickLookGeneratorQueryInterface
+// -----------------------------------------------------------------------------
+//	Implementation of the IUnknown QueryInterface function.
+//
+HRESULT QuickLookGeneratorQueryInterface(void *thisInstance,REFIID iid,LPVOID *ppv)
+{
+    CFUUIDRef interfaceID;
+
+    interfaceID = CFUUIDCreateFromUUIDBytes(kCFAllocatorDefault,iid);
+
+    if (CFEqual(interfaceID,kQLGeneratorCallbacksInterfaceID)){
+            /* If the Right interface was requested, bump the ref count,
+             * set the ppv parameter equal to the instance, and
+             * return good status.
+             */
+        ((QLGeneratorInterfaceStruct *)((QuickLookGeneratorPluginType *)thisInstance)->conduitInterface)->GenerateThumbnailForURL = GenerateThumbnailForURL;
+        ((QLGeneratorInterfaceStruct *)((QuickLookGeneratorPluginType *)thisInstance)->conduitInterface)->CancelThumbnailGeneration = CancelThumbnailGeneration;
+        ((QLGeneratorInterfaceStruct *)((QuickLookGeneratorPluginType *)thisInstance)->conduitInterface)->GeneratePreviewForURL = GeneratePreviewForURL;
+        ((QLGeneratorInterfaceStruct *)((QuickLookGeneratorPluginType *)thisInstance)->conduitInterface)->CancelPreviewGeneration = CancelPreviewGeneration;
+        ((QLGeneratorInterfaceStruct *)((QuickLookGeneratorPluginType*)thisInstance)->conduitInterface)->AddRef(thisInstance);
+        *ppv = thisInstance;
+        CFRelease(interfaceID);
+        return S_OK;
+    }else{
+        /* Requested interface unknown, bail with error. */
+        *ppv = NULL;
+        CFRelease(interfaceID);
+        return E_NOINTERFACE;
+    }
+}
+
+// -----------------------------------------------------------------------------
+// QuickLookGeneratorPluginAddRef
+// -----------------------------------------------------------------------------
+//	Implementation of reference counting for this type. Whenever an interface
+//	is requested, bump the refCount for the instance. NOTE: returning the
+//	refcount is a convention but is not required so don't rely on it.
+//
+ULONG QuickLookGeneratorPluginAddRef(void *thisInstance)
+{
+    ((QuickLookGeneratorPluginType *)thisInstance )->refCount += 1;
+    return ((QuickLookGeneratorPluginType*) thisInstance)->refCount;
+}
+
+// -----------------------------------------------------------------------------
+// QuickLookGeneratorPluginRelease
+// -----------------------------------------------------------------------------
+//	When an interface is released, decrement the refCount.
+//	If the refCount goes to zero, deallocate the instance.
+//
+ULONG QuickLookGeneratorPluginRelease(void *thisInstance)
+{
+    ((QuickLookGeneratorPluginType*)thisInstance)->refCount -= 1;
+    if (((QuickLookGeneratorPluginType*)thisInstance)->refCount == 0){
+        DeallocQuickLookGeneratorPluginType((QuickLookGeneratorPluginType*)thisInstance );
+        return 0;
+    }else{
+        return ((QuickLookGeneratorPluginType*) thisInstance )->refCount;
+    }
+}
+
+// -----------------------------------------------------------------------------
+//  QuickLookGeneratorPluginFactory
+// -----------------------------------------------------------------------------
+void *QuickLookGeneratorPluginFactory(CFAllocatorRef allocator,CFUUIDRef typeID)
+{
+    QuickLookGeneratorPluginType *result;
+    CFUUIDRef                 uuid;
+
+        /* If correct type is being requested, allocate an
+         * instance of kQLGeneratorTypeID and return the IUnknown interface.
+         */
+    if (CFEqual(typeID,kQLGeneratorTypeID)){
+        uuid = CFUUIDCreateFromString(kCFAllocatorDefault,CFSTR(PLUGIN_ID));
+        result = AllocQuickLookGeneratorPluginType(uuid);
+        CFRelease(uuid);
+        return result;
+    }
+        /* If the requested type is incorrect, return NULL. */
+    return NULL;
+}
+
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.