From 04fe20648d81c4b77d8732fa964a66dc7e2f88db Mon Sep 17 00:00:00 2001 From: OlehKulykov Date: Thu, 19 Feb 2015 15:12:32 +0100 Subject: [PATCH] Objective-C client speed optimizations --- CMakeLists.txt | 2 +- FayeCpp.podspec | 8 +- README.md | 2 +- appveyor.yml | 2 +- builds/ios/fayecpp.xcodeproj/project.pbxproj | 4 +- .../test_faye_static/ViewController.mm | 33 +- contrib/objc/FayeCppClient.mm | 435 +++++++++++------- fayecpp.h | 8 +- src/error.cpp | 22 +- src/websocket.cpp | 4 +- 10 files changed, 323 insertions(+), 197 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 6f47266..5cacc67 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -27,7 +27,7 @@ set(CPACK_PACKAGE_VERSION_MINOR "1") set(CPACK_PACKAGE_VERSION "${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}") set(CPACK_PACKAGE_VENDOR "info@resident.name") set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "${PACKAGE} ${PACKAGE_VERSION}") -set(SOVERSION "0.1.8") +set(SOVERSION "0.1.9") set(CPACK_SOURCE_PACKAGE_FILE_NAME "${CPACK_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION}") set(VERSION "${CPACK_PACKAGE_VERSION}") diff --git a/FayeCpp.podspec b/FayeCpp.podspec index 80fe14d..aaa3525 100644 --- a/FayeCpp.podspec +++ b/FayeCpp.podspec @@ -2,10 +2,10 @@ Pod::Spec.new do |s| # Common settings s.name = "FayeCpp" - s.version = "0.1.8" - s.summary = "Faye C++ client with objective-c client wrapper." + s.version = "0.1.9" + s.summary = "Faye C++ client with Objective-C client wrapper." s.description = <<-DESC -Faye C++ client with objective-c client wrapper. +Faye C++ client with Objective-C client wrapper. Library created with Pure C++ (features provided by Standard C++), without heavy STL and C++11 features. You can use Objective-C wrapper or C++ client directly. DESC @@ -45,7 +45,7 @@ You can use Objective-C wrapper or C++ client directly. 'libwebsockets/lib/alloc.c' s.resources = 'contrib/objc/FayeCpp.bundle' - s.compiler_flags = '-DHAVE_FAYECPP_CONFIG_H=1', '-DHAVE_CONFIG_H=1', '-DCMAKE_BUILD=1' + s.compiler_flags = '-DHAVE_FAYECPP_CONFIG_H=1', '-DHAVE_CONFIG_H=1', '-DCMAKE_BUILD=1', '-DHAVE_COREFOUNDATION_FRAMEWORK=1' s.xcconfig = { 'HEADER_SEARCH_PATHS' => '"${PODS_ROOT}/FayeCpp/contrib/objc" "${PODS_ROOT}/FayeCpp/libwebsockets/lib" "${PODS_ROOT}/FayeCpp/jansson/src"' } s.libraries = 'z', 'stdc++' s.framework = 'CoreFoundation' diff --git a/README.md b/README.md index 8926f16..9e0555a 100644 --- a/README.md +++ b/README.md @@ -39,7 +39,7 @@ git submodule update --init --recursive ### Installation with CocoaPods #### Podfile ```ruby -pod 'FayeCpp', '~> 0.1.8' +pod 'FayeCpp', '~> 0.1.9' ``` diff --git a/appveyor.yml b/appveyor.yml index 053b9fc..3bce28f 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,4 +1,4 @@ -version: 0.1.8.{build} +version: 0.1.9.{build} # branches to build branches: diff --git a/builds/ios/fayecpp.xcodeproj/project.pbxproj b/builds/ios/fayecpp.xcodeproj/project.pbxproj index 9e1d051..c6bb202 100644 --- a/builds/ios/fayecpp.xcodeproj/project.pbxproj +++ b/builds/ios/fayecpp.xcodeproj/project.pbxproj @@ -375,7 +375,7 @@ CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_ARC = NO; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; @@ -424,7 +424,7 @@ CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_ARC = NO; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; diff --git a/builds/ios/test_faye_static/test_faye_static/ViewController.mm b/builds/ios/test_faye_static/test_faye_static/ViewController.mm index 402da81..423072e 100644 --- a/builds/ios/test_faye_static/test_faye_static/ViewController.mm +++ b/builds/ios/test_faye_static/test_faye_static/ViewController.mm @@ -134,8 +134,14 @@ - (IBAction) onSendText:(id)sender #if defined(OBJC_CLIENT) if (_client) { - [_client sendMessage:@{@"text" : [_textField text]} - toChannel:@"/seminars/5322e93d8ee60a422400008f"]; + NSMutableDictionary * dict = [NSMutableDictionary dictionary]; + dict[@"text"] = [_textField text]; + dict[@"YES"] = @YES; + dict[@"NO"] = @NO; + dict[@"int1"] = @123; + dict[@"float1"] = @3.14; + + [_client sendMessage:dict toChannel:@"/seminars/5322e93d8ee60a422400008f"]; } #else if (_client) @@ -170,6 +176,29 @@ - (IBAction) onCreate:(id)sender [client setSSLDataSource:self]; [client setUrlString:@"http://messages.presentain.com:80/faye"]; self.client = client; + + NSMutableDictionary * ext = [NSMutableDictionary dictionary]; + NSMutableArray * arr = [NSMutableArray array]; + [arr addObject:@"Hello"]; + [arr addObject:@"World"]; + [arr addObject:[NSNull null]]; + [arr addObject:@231231233234324]; + [arr addObject:@3.142352532111]; + [arr addObject:@YES]; + [arr addObject:@NO]; + ext[@"arr"] = arr; + ext[@"asd"] = @"asd"; + ext[@"YES"] = @YES; + ext[@"NULL"] = [NSNull null]; + ext[@"int"] = @-324432603623523111; + + [_client setExtValue:ext]; + + NSDictionary * ext1 = [_client extValue]; + if (![ext isEqualToDictionary:ext1]) + { + assert(0); + } #else if (_client) { diff --git a/contrib/objc/FayeCppClient.mm b/contrib/objc/FayeCppClient.mm index d21d90c..159e8cb 100644 --- a/contrib/objc/FayeCppClient.mm +++ b/contrib/objc/FayeCppClient.mm @@ -22,12 +22,15 @@ #import "FayeCppClient.h" - +#import #ifndef __has_feature #define __has_feature(x) 0 #endif +#if __has_feature(objc_arc) +#error "ARC enabled. Need disable for this file." +#endif #include @@ -46,9 +49,21 @@ NSString * kFayeCppErrorPlaceInTheCodeKey = @"kFayeCppErrorPlaceInTheCodeKey"; NSString * kFayeCppErrorChannelKey = @"kFayeCppErrorChannelKey"; - using namespace FayeCpp; +class CFHelper +{ +public: + static CFStringRef string(const REString & string); + static CFMutableArrayRef array(const REVariantList & list); + static CFTypeRef object(const REVariant & variant); + static CFMutableDictionaryRef dict(const REVariantMap & map); + static CFErrorRef error(Error * error); + static CFURLRef url(const REString & string); + static REVariant variant(CFTypeRef object); + static void dictToMap(CFDictionaryRef dict, REVariantMap * map); +}; + class FayeCppClientSSLDataSourceWrapper : public SSLDataSource { public: @@ -110,15 +125,8 @@ return FayeCpp::REString(); } - FayeCppClientSSLDataSourceWrapper() : objcClient(NULL) - { - - } - - virtual ~FayeCppClientSSLDataSourceWrapper() - { - - } + FayeCppClientSSLDataSourceWrapper() : objcClient(NULL) { } + virtual ~FayeCppClientSSLDataSourceWrapper() { } }; class FayeCppDelegateWrapper : public Delegate @@ -176,9 +184,10 @@ virtual void onFayeClientSubscribedToChannel(FayeCpp::Client * client, id d = objcClient ? [objcClient delegate] : nil; if (d && [d respondsToSelector:@selector(onFayeClient:subscribedToChannel:)]) { - NSString * ch = FayeCppDelegateWrapper::objcString(channel); + CFStringRef ch = CFHelper::string(channel); dispatch_async(dispatch_get_main_queue(), ^{ - [d onFayeClient:objcClient subscribedToChannel:ch]; + [d onFayeClient:objcClient subscribedToChannel:(NSString *)ch]; + if (ch) CFRelease(ch); }); } } @@ -189,9 +198,10 @@ virtual void onFayeClientUnsubscribedFromChannel(FayeCpp::Client * client, id d = objcClient ? [objcClient delegate] : nil; if (d && [d respondsToSelector:@selector(onFayeClient:unsubscribedFromChannel:)]) { - NSString * ch = FayeCppDelegateWrapper::objcString(channel); + CFStringRef ch = CFHelper::string(channel); dispatch_async(dispatch_get_main_queue(), ^{ - [d onFayeClient:objcClient unsubscribedFromChannel:ch]; + [d onFayeClient:objcClient unsubscribedFromChannel:(NSString *)ch]; + if (ch) CFRelease(ch); }); } } @@ -203,13 +213,25 @@ virtual void onFayeClientReceivedMessageFromChannel(FayeCpp::Client * client, id d = objcClient ? [objcClient delegate] : nil; if (d && [d respondsToSelector:@selector(onFayeClient:receivedMessage:fromChannel:)]) { - NSString * ch = FayeCppDelegateWrapper::objcString(channel); - id obj = FayeCppDelegateWrapper::objcObject(message); - if (obj && [obj isKindOfClass:[NSDictionary class]]) + CFStringRef ch = CFHelper::string(channel); + CFTypeRef obj = CFHelper::object(message); + bool isPassed = false; + if (obj) { - dispatch_async(dispatch_get_main_queue(), ^{ - [d onFayeClient:objcClient receivedMessage:(NSDictionary*)obj fromChannel:ch]; - }); + if (CFGetTypeID(obj) == CFDictionaryGetTypeID()) + { + isPassed = true; + dispatch_async(dispatch_get_main_queue(), ^{ + [d onFayeClient:objcClient receivedMessage:(NSDictionary *)obj fromChannel:(NSString *)ch]; + if (obj) CFRelease(obj); + if (ch) CFRelease(ch); + }); + } + } + if (!isPassed) + { + if (obj) CFRelease(obj); + if (ch) CFRelease(ch); } } } @@ -226,190 +248,273 @@ virtual void onFayeErrorString(FayeCpp::Client * client, id d = objcClient ? [objcClient delegate] : nil; if (d && [d respondsToSelector:@selector(onFayeClient:error:)]) { - NSError * error = FayeCppDelegateWrapper::objcError(client->lastError()); - + CFErrorRef error = CFHelper::error(client->lastError()); dispatch_async(dispatch_get_main_queue(), ^{ - [d onFayeClient:objcClient error:error]; + [d onFayeClient:objcClient error:(NSError *)error]; + if (error) CFRelease(error); }); } } - FayeCppDelegateWrapper() : objcClient(NULL) - { - - } - - virtual ~FayeCppDelegateWrapper() - { - - } - - static NSString * objcString(const REString & string); - static id objcObject(const REVariant & variant); - static NSMutableArray * objcArray(const REVariantList & list); - static NSMutableDictionary * objcDict(const REVariantMap & map); - static NSError * objcError(Error * error); - static void objcDictToMap(NSDictionary * dict, REVariantMap & map); - static REVariant objcObjectToVariant(id object); + FayeCppDelegateWrapper() : objcClient(NULL) { } + virtual ~FayeCppDelegateWrapper() { } }; -NSError * FayeCppDelegateWrapper::objcError(Error * error) +void CFHelper::dictToMap(CFDictionaryRef dict, REVariantMap * map) { - NSMutableDictionary * userInfo = nil; - NSInteger code = (NSInteger)kCFHostErrorUnknown; - NSString * domain = nil; - if (error) + if (dict && map) { - userInfo = [NSMutableDictionary dictionary]; - REVariantMap::Iterator iterator = error->userInfo().iterator(); - while (iterator.next()) + const CFIndex count = CFDictionaryGetCount(dict); + if (count > 0) { - if (iterator.key().isEqual(kErrorLocalizedDescriptionKey)) + const void ** values = (const void **)malloc(sizeof(const void *) * count); + const void ** keys = (const void **)malloc(sizeof(const void *) * count); + if (values && keys) { - [userInfo setObject:FayeCppDelegateWrapper::objcString(iterator.value().toString()) - forKey:NSLocalizedDescriptionKey]; + CFDictionaryGetKeysAndValues(dict, keys, values); + for (CFIndex i = 0; i < count; i++) + { + CFTypeRef key = (CFTypeRef)keys[i]; + if (CFGetTypeID(key) == CFStringGetTypeID()) + { + REVariant kVariant = CFHelper::variant(key); + if (kVariant.isString()) + { + map->setKeyValue(kVariant.toString(), CFHelper::variant((CFTypeRef)values[i])); + } + } + } } - else if (iterator.key().isEqual(kErrorURLKey)) + if (keys) free(keys); + if (values) free(values); + } + } +} + +REVariant CFHelper::variant(CFTypeRef object) +{ + if (object) + { + const CFTypeID type = CFGetTypeID(object); + if (type == CFStringGetTypeID()) + { + REVariant var; + const CFIndex len = CFStringGetLength((CFStringRef)object); + if (len > 0) { - NSURL * url = [NSURL URLWithString:FayeCppDelegateWrapper::objcString(iterator.value().toString())]; - if (url) [userInfo setObject:url forKey:NSURLErrorKey]; + const size_t buffSize = (len + 1) * sizeof(wchar_t); + char * buff = (char *)malloc(buffSize); + if (buff) + { + if (CFStringGetCString((CFStringRef)object, buff, (CFIndex)buffSize, kCFStringEncodingUTF8)) var = buff; + free(buff); + } } - else if (iterator.key().isEqual(kErrorPlaceInTheCodeKey)) + if (var.type() != REVariant::TypeString) var = ""; + return var; + } + else if (type == CFDictionaryGetTypeID()) + { + REVariantMap m; + CFHelper::dictToMap((CFDictionaryRef)object, &m); + return REVariant(m); + } + else if (type == CFArrayGetTypeID()) + { + REVariantList l; + const CFIndex count = CFArrayGetCount((CFArrayRef)object); + for (CFIndex i = 0; i < count; i++) { - [userInfo setObject:FayeCppDelegateWrapper::objcString(iterator.value().toString()) - forKey:kFayeCppErrorPlaceInTheCodeKey]; + CFTypeRef element = CFArrayGetValueAtIndex((CFArrayRef)object, i); + if (element) l.add(CFHelper::variant(element)); } - else if (iterator.key().isEqual(kErrorChannelKey)) + return REVariant(l); + } + else if (type == CFBooleanGetTypeID()) + { + return CFEqual(object, kCFBooleanTrue) ? REVariant(true) : REVariant(false); + } + else if (type == CFNumberGetTypeID()) + { + const CFNumberType numType = CFNumberGetType((CFNumberRef)object); + switch (numType) { - [userInfo setObject:FayeCppDelegateWrapper::objcString(iterator.value().toString()) - forKey:kFayeCppErrorChannelKey]; + case kCFNumberSInt8Type: { SInt8 v = 0; if (CFNumberGetValue((CFNumberRef)object, numType, &v)) return REVariant((int)v); } break; + case kCFNumberSInt16Type: { SInt16 v = 0; if (CFNumberGetValue((CFNumberRef)object, numType, &v)) return REVariant((int)v); } break; + case kCFNumberSInt32Type: { SInt32 v = 0; if (CFNumberGetValue((CFNumberRef)object, numType, &v)) return REVariant((int)v); } break; + case kCFNumberSInt64Type: { SInt64 v = 0; if (CFNumberGetValue((CFNumberRef)object, numType, &v)) return REVariant((long long)v); } break; + case kCFNumberFloat32Type: { Float32 v = 0; if (CFNumberGetValue((CFNumberRef)object, numType, &v)) return REVariant((double)v); } break; + case kCFNumberFloat64Type: { Float64 v = 0; if (CFNumberGetValue((CFNumberRef)object, numType, &v)) return REVariant((double)v); } break; + case kCFNumberCharType: { char v = 0; if (CFNumberGetValue((CFNumberRef)object, numType, &v)) return REVariant((int)v); } break; + case kCFNumberShortType: { short v = 0; if (CFNumberGetValue((CFNumberRef)object, numType, &v)) return REVariant((int)v); } break; + case kCFNumberIntType: { int v = 0; if (CFNumberGetValue((CFNumberRef)object, numType, &v)) return REVariant(v); } break; + case kCFNumberLongType: { long v = 0; if (CFNumberGetValue((CFNumberRef)object, numType, &v)) return REVariant((long long)v); } break; + case kCFNumberLongLongType: { long long v = 0; if (CFNumberGetValue((CFNumberRef)object, numType, &v)) return REVariant((long long)v); } break; + case kCFNumberFloatType: { float v = 0; if (CFNumberGetValue((CFNumberRef)object, numType, &v)) return REVariant((double)v); } break; + case kCFNumberDoubleType: { double v = 0; if (CFNumberGetValue((CFNumberRef)object, numType, &v)) return REVariant((double)v); } break; + case kCFNumberCFIndexType: { CFIndex v = 0; if (CFNumberGetValue((CFNumberRef)object, numType, &v)) return REVariant((long long)v); } break; + case kCFNumberNSIntegerType: { NSInteger v = 0; if (CFNumberGetValue((CFNumberRef)object, numType, &v)) return REVariant((long long)v); } break; + case kCFNumberCGFloatType: { CGFloat v = 0; if (CFNumberGetValue((CFNumberRef)object, numType, &v)) return REVariant((double)v); } break; + default: + break; } } - code = (NSInteger)error->code(); - domain = FayeCppDelegateWrapper::objcString(error->domain()); - if ([userInfo count] == 0) userInfo = nil; - } - else - { - domain = [NSString stringWithUTF8String:kErrorDomainClient]; } + return REVariant(); +} - return [NSError errorWithDomain:domain code:code userInfo:userInfo]; +CFURLRef CFHelper::url(const REString & string) +{ + const CFIndex len = string.length(); + return (len > 0) ? CFURLCreateWithBytes(NULL, (const UInt8 *)string.UTF8String(), len, kCFStringEncodingUTF8, NULL) : NULL; } -id FayeCppDelegateWrapper::objcObject(const REVariant & variant) +CFErrorRef CFHelper::error(Error * error) { - switch (variant.type()) + CFMutableDictionaryRef userInfo = NULL; + CFIndex code = (CFIndex)kCFNetServiceErrorUnknown; + CFStringRef domain = NULL; + if (error) { - case REVariant::TypeInteger: - return [NSNumber numberWithLongLong:variant.toInt64()]; - break; - case REVariant::TypeUnsignedInteger: - return [NSNumber numberWithUnsignedLongLong:variant.toUInt64()]; - break; - case REVariant::TypeReal: - return [NSNumber numberWithDouble:variant.toDouble()]; - break; - case REVariant::TypeBool: - return [NSNumber numberWithBool:(BOOL)variant.toBool()]; - break; - case REVariant::TypeString: - return FayeCppDelegateWrapper::objcString(variant.toString()); - break; - case REVariant::TypeMap: - return FayeCppDelegateWrapper::objcDict(variant.toMap()); - break; - case REVariant::TypeList: - return FayeCppDelegateWrapper::objcArray(variant.toList()); - break; - default: - break; + userInfo = CFDictionaryCreateMutable(NULL, 4, &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + if (userInfo) + { + REVariantMap::Iterator iterator = error->userInfo().iterator(); + while (iterator.next()) + { + if (iterator.key().isEqual(kErrorLocalizedDescriptionKey)) + { + CFStringRef value = CFHelper::string(iterator.value().toString()); + if (value) + { + CFDictionarySetValue(userInfo, kCFErrorLocalizedDescriptionKey, value); + CFRelease(value); + } + } + else if (iterator.key().isEqual(kErrorURLKey)) + { + CFURLRef url = CFHelper::url(iterator.value().toString()); + if (url) + { + CFDictionarySetValue(userInfo, kCFErrorURLKey, url); + CFRelease(url); + } + } + else if (iterator.key().isEqual(kErrorPlaceInTheCodeKey)) + { + CFStringRef value = CFHelper::string(iterator.value().toString()); + if (value) + { + CFDictionarySetValue(userInfo, (CFStringRef)kFayeCppErrorPlaceInTheCodeKey, value); + CFRelease(value); + } + } + else if (iterator.key().isEqual(kErrorChannelKey)) + { + CFStringRef value = CFHelper::string(iterator.value().toString()); + if (value) + { + CFDictionarySetValue(userInfo, (CFStringRef)kFayeCppErrorChannelKey, value); + CFRelease(value); + } + } + } + } + code = (CFIndex)error->code(); + domain = CFHelper::string(error->domain()); + } + else + { + domain = CFStringCreateWithCString(NULL, kErrorDomainClient, kCFStringEncodingUTF8); } - return [NSNull null]; -} -NSMutableArray * FayeCppDelegateWrapper::objcArray(const REVariantList & list) -{ - NSMutableArray * arr = [NSMutableArray array]; - REVariantList::Iterator i = list.iterator(); - while (i.next()) + CFErrorRef err = NULL; + if (domain) { - [arr addObject:FayeCppDelegateWrapper::objcObject(i.value())]; + err = CFErrorCreate(NULL, domain, code, userInfo); + CFRelease(domain); } - return arr; + if (userInfo) CFRelease(userInfo); + return err; } -NSMutableDictionary * FayeCppDelegateWrapper::objcDict(const REVariantMap & map) +CFMutableDictionaryRef CFHelper::dict(const REVariantMap & map) { - NSMutableDictionary * dict = [NSMutableDictionary dictionary]; - REVariantMap::Iterator i = map.iterator(); - while (i.next()) + CFMutableDictionaryRef d = CFDictionaryCreateMutable(NULL, 2, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + if (d) { - [dict setObject:FayeCppDelegateWrapper::objcObject(i.value()) - forKey:FayeCppDelegateWrapper::objcString(i.key())]; + REVariantMap::Iterator i = map.iterator(); + while (i.next()) + { + CFStringRef key = CFHelper::string(i.key()); + CFTypeRef value = CFHelper::object(i.value()); + if (key && value) CFDictionarySetValue(d, key, value); + + if (key) CFRelease(key); + if (value) CFRelease(value); + } } - return dict; + return d; } -NSString * FayeCppDelegateWrapper::objcString(const REString & string) +CFStringRef CFHelper::string(const REString & string) { const char * s = string.UTF8String(); - return s ? [NSString stringWithUTF8String:s] : @""; + return s ? CFStringCreateWithCString(NULL, s, kCFStringEncodingUTF8) : CFSTR(""); } -REVariant FayeCppDelegateWrapper::objcObjectToVariant(id object) +CFMutableArrayRef CFHelper::array(const REVariantList & list) { - if ([object isKindOfClass:[NSDictionary class]]) - { - REVariantMap m; - FayeCppDelegateWrapper::objcDictToMap((NSDictionary *)object, m); - return REVariant(m); - } - else if ([object isKindOfClass:[NSArray class]]) + CFMutableArrayRef arr = CFArrayCreateMutable(NULL, 2, &kCFTypeArrayCallBacks); + if (arr) { - REVariantList l; - for (id obj in (NSArray*)object) + REVariantList::Iterator i = list.iterator(); + while (i.next()) { - l.add(FayeCppDelegateWrapper::objcObjectToVariant(obj)); - } - return REVariant(l); - } - else if ([object isKindOfClass:[NSString class]]) - { - return REVariant([(NSString*)object UTF8String]); - } - else if ([object isKindOfClass:[NSNumber class]]) - { - NSNumber * num = (NSNumber *)object; - if (strcmp([num objCType], @encode(BOOL)) == 0) return REVariant((bool)[num boolValue]); - else - { - switch (CFNumberGetType((CFNumberRef)num)) { - case kCFNumberFloatType: - case kCFNumberDoubleType: - case kCFNumberCGFloatType: - case kCFNumberFloat32Type: - case kCFNumberFloat64Type: - return REVariant((double)[num doubleValue]); - break; - - default: - return REVariant((long long)[num longLongValue]); - break; + CFTypeRef obj = CFHelper::object(i.value()); + if (obj) + { + CFArrayAppendValue(arr, obj); + CFRelease(obj); } } } - return REVariant(); + return arr; } -void FayeCppDelegateWrapper::objcDictToMap(NSDictionary * dict, REVariantMap & map) +CFTypeRef CFHelper::object(const REVariant & variant) { - [dict enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL * stop){ - if ([key isKindOfClass:[NSString class]]) + switch (variant.type()) + { + case REVariant::TypeInteger: + case REVariant::TypeUnsignedInteger: { - map[[(NSString *)key UTF8String]] = FayeCppDelegateWrapper::objcObjectToVariant(obj); + const long long v = variant.toInt64(); + return CFNumberCreate(NULL, kCFNumberLongLongType, &v); } - }]; + break; + case REVariant::TypeReal: + { + const double v = variant.toDouble(); + return CFNumberCreate(NULL, kCFNumberDoubleType, &v); + } + break; + case REVariant::TypeBool: + return variant.toBool() ? kCFBooleanTrue : kCFBooleanFalse; + break; + case REVariant::TypeString: + return CFHelper::string(variant.toString()); + break; + case REVariant::TypeMap: + return CFHelper::dict(variant.toMap()); + break; + case REVariant::TypeList: + return CFHelper::array(variant.toList()); + break; + default: + break; + } + return kCFNull; } #if !defined(SAFE_RETAIN) && !__has_feature(objc_arc) @@ -448,8 +553,8 @@ - (id) extValue if (e.type() != REVariant::TypeNone) { - id ext = FayeCppDelegateWrapper::objcObject(e); - return ext; + CFTypeRef ext = CFHelper::object(e); + return (id)CFAutorelease(ext); } return nil; @@ -457,21 +562,7 @@ - (id) extValue - (void) setExtValue:(id) value { - if (!_cppClient) return; - - if (value) - { - if ([value isKindOfClass:[NSNull class]]) _cppClient->setExtValue(REVariant()); - else - { - REVariant e = FayeCppDelegateWrapper::objcObjectToVariant(value); - _cppClient->setExtValue(e); - } - } - else - { - _cppClient->setExtValue(REVariant()); - } + if (_cppClient) _cppClient->setExtValue(CFHelper::variant((CFTypeRef)value)); } - (BOOL) isUsingIPV6 @@ -510,7 +601,7 @@ - (BOOL) sendMessage:(NSDictionary *) message if (_cppClient && message && channel) { REVariantMap map; - FayeCppDelegateWrapper::objcDictToMap(message, map); + CFHelper::dictToMap((CFDictionaryRef)message, &map); return _cppClient->sendMessageToChannel(map, [channel UTF8String]); } return NO; diff --git a/fayecpp.h b/fayecpp.h index 86260b3..e109971 100644 --- a/fayecpp.h +++ b/fayecpp.h @@ -28,7 +28,11 @@ * Faye C++ client main and one header file. * All class interfaces added to namespace, preventing include files mess. * - * Changes on version 0.1.8 (current): + * Changes on version 0.1.9 (current): + * - Objective-C client wrapper speed optimizations(used only NON-ARC mode and CoreFoundation framework). + * - Apple localization bundle fix. + * + * Changes on version 0.1.8: * - Added additional error processing with new Error class. * * Changes on version 0.1.7: @@ -72,7 +76,7 @@ #define FAYECPP_VERSION_MAJOR 0 #define FAYECPP_VERSION_MINOR 1 -#define FAYECPP_VERSION_PATCH 8 +#define FAYECPP_VERSION_PATCH 9 #if !defined(HAVE_SUITABLE_QT_VERSION) diff --git a/src/error.cpp b/src/error.cpp index cfeeb86..3ec6419 100644 --- a/src/error.cpp +++ b/src/error.cpp @@ -43,21 +43,21 @@ namespace FayeCpp { void init() { CFBundleRef mainBundle = CFBundleGetMainBundle(); - if (!mainBundle) return; - - CFStringRef resourceName = CFStringCreateWithCString(NULL, kFayeCppBundleName ,kCFStringEncodingUTF8); - if (resourceName) + if (mainBundle) { - CFURLRef url = CFBundleCopyResourceURL(mainBundle, resourceName, CFSTR("bundle"), NULL); - CFRelease(resourceName); - if (url) + CFStringRef resourceName = CFStringCreateWithCString(NULL, kFayeCppBundleName ,kCFStringEncodingUTF8); + if (resourceName) { - _localizedBundle = CFBundleCreate(NULL, url); - CFRelease(url); + CFURLRef url = CFBundleCopyResourceURL(mainBundle, resourceName, CFSTR("bundle"), NULL); + CFRelease(resourceName); + if (url) + { + _localizedBundle = CFBundleCreate(NULL, url); + CFRelease(url); + } } + _localizedTableName = CFStringCreateWithCString(NULL, kFayeCppBundleLocalizationTableName ,kCFStringEncodingUTF8); } - CFRelease(mainBundle); - _localizedTableName = CFStringCreateWithCString(NULL, kFayeCppBundleLocalizationTableName ,kCFStringEncodingUTF8); } public: diff --git a/src/websocket.cpp b/src/websocket.cpp index 5a3cc37..3349685 100644 --- a/src/websocket.cpp +++ b/src/websocket.cpp @@ -344,7 +344,7 @@ namespace FayeCpp { { #if defined(HAVE_FUNCTION_PTHREAD_SETNAME_NP) && defined(__APPLE__) pthread_setname_np("FayeCpp WebSocket workThread"); -#endif +#endif WebSocket * socket = static_cast(somePointer); socket->workMethod(); pthread_t * t = socket->_workThread; @@ -594,6 +594,8 @@ namespace FayeCpp { WebSocket::~WebSocket() { + FAYECPP_DEBUG_LOG("DESTRUCTOR ~WebSocket()"); + #if defined(HAVE_PTHREAD_H) pthread_mutex_destroy(&_mutex); #elif defined(__RE_USING_WINDOWS_THREADS__)