Skip to content
Browse files

Changed the XML parser from TouchXML to TBXML, which results in notic…

…eable faster performance
  • Loading branch information...
1 parent 2cb746b commit 26db12fd0756114bbcce66a6b46e7f0b38624f67 Adrian Kosmaczewski committed
Showing with 2,192 additions and 2,598 deletions.
  1. +1 −0 .gitignore
  2. +7 −2 Classes/Controllers/CommentsController.m
  3. +66 −53 Classes/Helpers/FatFreeCRMProxy.m
  4. +8 −3 Classes/Models/BaseEntity.h
  5. +37 −34 Classes/Models/BaseEntity.m
  6. +1 −1 Classes/Models/Campaign.h
  7. +23 −65 Classes/Models/Campaign.m
  8. +1 −1 Classes/Models/Comment.h
  9. +4 −12 Classes/Models/Comment.m
  10. +1 −1 Classes/Models/CompanyAccount.h
  11. +15 −38 Classes/Models/CompanyAccount.m
  12. +1 −3 Classes/Models/Contact.h
  13. +71 −129 Classes/Models/Contact.m
  14. +1 −1 Classes/Models/Lead.h
  15. +7 −18 Classes/Models/Lead.m
  16. +1 −1 Classes/Models/Opportunity.h
  17. +13 −41 Classes/Models/Opportunity.m
  18. +1 −1 Classes/Models/Task.h
  19. +9 −28 Classes/Models/Task.m
  20. +1 −1 Classes/Models/User.h
  21. +29 −73 Classes/Models/User.m
  22. +166 −0 Externals/Google Toolbox for Mac/GTMDefines.h
  23. +66 −0 Externals/Google Toolbox for Mac/GTMNSString+HTML.h
  24. +522 −0 Externals/Google Toolbox for Mac/GTMNSString+HTML.m
  25. +66 −0 Externals/TBXML/NSDataAdditions.h
  26. +309 −0 Externals/TBXML/NSDataAdditions.m
  27. +130 −0 Externals/TBXML/TBXML.h
  28. +595 −0 Externals/TBXML/TBXML.m
  29. +0 −67 Externals/TouchXML/CXMLDocument.h
  30. +0 −240 Externals/TouchXML/CXMLDocument.m
  31. +0 −40 Externals/TouchXML/CXMLDocument_PrivateExtensions.h
  32. +0 −53 Externals/TouchXML/CXMLDocument_PrivateExtensions.m
  33. +0 −50 Externals/TouchXML/CXMLElement.h
  34. +0 −142 Externals/TouchXML/CXMLElement.m
  35. +0 −38 Externals/TouchXML/CXMLElement_CreationExtensions.h
  36. +0 −55 Externals/TouchXML/CXMLElement_CreationExtensions.m
  37. +0 −37 Externals/TouchXML/CXMLElement_ElementTreeExtensions.h
  38. +0 −44 Externals/TouchXML/CXMLElement_ElementTreeExtensions.m
  39. +0 −84 Externals/TouchXML/CXMLNode.h
  40. +0 −317 Externals/TouchXML/CXMLNode.m
  41. +0 −40 Externals/TouchXML/CXMLNode_PrivateExtensions.h
  42. +0 −98 Externals/TouchXML/CXMLNode_PrivateExtensions.m
  43. +0 −36 Externals/TouchXML/CXMLNode_XPathExtensions.h
  44. +0 −79 Externals/TouchXML/CXMLNode_XPathExtensions.m
  45. +0 −47 Externals/TouchXML/Creation/CXMLDocument_CreationExtensions.h
  46. +0 −53 Externals/TouchXML/Creation/CXMLDocument_CreationExtensions.m
  47. +0 −54 Externals/TouchXML/Creation/CXMLNode_CreationExtensions.h
  48. +0 −104 Externals/TouchXML/Creation/CXMLNode_CreationExtensions.m
  49. +0 −53 Externals/TouchXML/Tidy/CTidy.h
  50. +0 −228 Externals/TouchXML/Tidy/CTidy.m
  51. +0 −37 Externals/TouchXML/TouchXML.h
  52. +40 −96 Senbei.xcodeproj/project.pbxproj
View
1 .gitignore
@@ -1,5 +1,6 @@
Releases
build
+*.mode1v3
*.mode2v3
*.pbxuser
View
9 Classes/Controllers/CommentsController.m
@@ -180,8 +180,13 @@ - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
Comment *comment = [_comments objectAtIndex:indexPath.row];
- return [comment.comment sizeWithFont:[UIFont systemFontOfSize:17.0]
- constrainedToSize:CGSizeMake(300.0, 4000.0)].height + 30.0;
+ CGFloat height = [comment.comment sizeWithFont:[UIFont systemFontOfSize:17.0]
+ constrainedToSize:CGSizeMake(300.0, 4000.0)].height + 30.0;
+ if (height < 44.0)
+ {
+ height = 44.0;
+ }
+ return height;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
View
119 Classes/Helpers/FatFreeCRMProxy.m
@@ -40,7 +40,7 @@
#import "ASIHTTPRequest.h"
#import "ASIFormDataRequest.h"
#import "Definitions.h"
-#import "TouchXML.h"
+#import "TBXML.h"
#import "CompanyAccount.h"
#import "Opportunity.h"
#import "Contact.h"
@@ -71,7 +71,8 @@ - (void)processGetContactsRequest:(ASIHTTPRequest *)request;
- (void)processGetCommentsRequest:(ASIHTTPRequest *)request;
- (void)processLoginRequest:(ASIHTTPRequest *)request;
- (void)processGetTasksRequest:(ASIHTTPRequest *)request;
-- (NSArray *)deserializeXML:(NSString *)xmlString forXPath:(NSString *)xpath andClass:(Class)klass;
+- (NSArray *)deserializeXML:(NSData *)xmlData forXPath:(NSString *)xpath andClass:(Class)klass;
+- (NSArray *)deserializeXMLElement:(TBXMLElement *)element forXPath:(NSString *)xpath andClass:(Class)klass;
@end
@@ -397,28 +398,37 @@ - (void)notifyError:(NSError *)error
#pragma mark -
#pragma mark Request processing methods
-- (NSArray *)deserializeXML:(NSString *)xmlString forXPath:(NSString *)xpath andClass:(Class)klass
+- (NSArray *)deserializeXMLElement:(TBXMLElement *)element forXPath:(NSString *)xpath andClass:(Class)klass
{
- CXMLDocument *xml = [[CXMLDocument alloc] initWithXMLString:xmlString
- options:0
- error:nil];
- NSArray *xmlNodes = [xml nodesForXPath:xpath error:nil];
- NSMutableArray *objects = [NSMutableArray arrayWithCapacity:[xmlNodes count]];
- for (CXMLElement *element in xmlNodes)
+ NSMutableArray *objects = [NSMutableArray array];
+ if (element)
{
- id item = [[klass alloc] initWithCXMLElement:element];
- [objects addObject:item];
- [item release];
+ TBXMLElement *child = [TBXML childElementNamed:xpath parentElement:element];
+
+ while (child != nil)
+ {
+ id item = [[klass alloc] initWithTBXMLElement:child];
+ [objects addObject:item];
+ [item release];
+
+ child = [TBXML nextSiblingNamed:xpath searchFromElement:child];
+ }
}
- [xml release];
return objects;
}
+- (NSArray *)deserializeXML:(NSData *)xmlData forXPath:(NSString *)xpath andClass:(Class)klass
+{
+ TBXML *tbxml = [TBXML tbxmlWithXMLData:xmlData];
+ TBXMLElement *root = tbxml.rootXMLElement;
+ return [self deserializeXMLElement:root forXPath:xpath andClass:klass];
+}
+
- (void)processGetAccountsRequest:(ASIHTTPRequest *)request
{
- NSString *response = [request responseString];
+ NSData *response = [request responseData];
NSArray *accounts = [self deserializeXML:response
- forXPath:@"//account"
+ forXPath:@"account"
andClass:NSClassFromString(@"CompanyAccount")];
NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys:accounts, @"data", nil];
NSNotification *notif = [NSNotification notificationWithName:FatFreeCRMProxyDidRetrieveAccountsNotification
@@ -429,9 +439,9 @@ - (void)processGetAccountsRequest:(ASIHTTPRequest *)request
- (void)processGetCampaignsRequest:(ASIHTTPRequest *)request
{
- NSString *response = [request responseString];
+ NSData *response = [request responseData];
NSArray *campaigns = [self deserializeXML:response
- forXPath:@"//campaign"
+ forXPath:@"campaign"
andClass:NSClassFromString(@"Campaign")];
NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys:campaigns, @"data", nil];
NSNotification *notif = [NSNotification notificationWithName:FatFreeCRMProxyDidRetrieveCampaignsNotification
@@ -442,9 +452,9 @@ - (void)processGetCampaignsRequest:(ASIHTTPRequest *)request
- (void)processGetLeadsRequest:(ASIHTTPRequest *)request
{
- NSString *response = [request responseString];
+ NSData *response = [request responseData];
NSArray *leads = [self deserializeXML:response
- forXPath:@"//lead"
+ forXPath:@"lead"
andClass:NSClassFromString(@"Lead")];
NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys:leads, @"data", nil];
NSNotification *notif = [NSNotification notificationWithName:FatFreeCRMProxyDidRetrieveLeadsNotification
@@ -455,9 +465,9 @@ - (void)processGetLeadsRequest:(ASIHTTPRequest *)request
- (void)processGetOpportunitiesRequest:(ASIHTTPRequest *)request
{
- NSString *response = [request responseString];
+ NSData *response = [request responseData];
NSArray *opportunities = [self deserializeXML:response
- forXPath:@"//opportunity"
+ forXPath:@"opportunity"
andClass:NSClassFromString(@"Opportunity")];
NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys:opportunities, @"data", nil];
NSNotification *notif = [NSNotification notificationWithName:FatFreeCRMProxyDidRetrieveOpportunitiesNotification
@@ -468,9 +478,9 @@ - (void)processGetOpportunitiesRequest:(ASIHTTPRequest *)request
- (void)processGetContactsRequest:(ASIHTTPRequest *)request
{
- NSString *response = [request responseString];
+ NSData *response = [request responseData];
NSArray *contacts = [self deserializeXML:response
- forXPath:@"//contact"
+ forXPath:@"contact"
andClass:NSClassFromString(@"Contact")];
NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys:contacts, @"data", nil];
NSNotification *notif = [NSNotification notificationWithName:FatFreeCRMProxyDidRetrieveContactsNotification
@@ -481,9 +491,9 @@ - (void)processGetContactsRequest:(ASIHTTPRequest *)request
- (void)processGetCommentsRequest:(ASIHTTPRequest *)request
{
- NSString *response = [request responseString];
+ NSData *response = [request responseData];
NSArray *comments = [self deserializeXML:response
- forXPath:@"/comments/comment"
+ forXPath:@"comment"
andClass:NSClassFromString(@"Comment")];
NSDictionary *userInfo = request.userInfo;
@@ -498,13 +508,12 @@ - (void)processGetCommentsRequest:(ASIHTTPRequest *)request
- (void)processLoginRequest:(ASIHTTPRequest *)request
{
- NSString *response = [request responseString];
- NSArray *users = [self deserializeXML:response
- forXPath:@"/user"
- andClass:NSClassFromString(@"User")];
-
- User *user = [users objectAtIndex:0];
+ NSData *response = [request responseData];
+ TBXML *tbxml = [TBXML tbxmlWithXMLData:response];
+ TBXMLElement *root = tbxml.rootXMLElement;
+ User *user = [[User alloc] initWithTBXMLElement:root];
NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys:user, @"user", nil];
+ [user release];
NSNotification *notif = [NSNotification notificationWithName:FatFreeCRMProxyDidLoginNotification
object:self
userInfo:dict];
@@ -513,28 +522,32 @@ - (void)processLoginRequest:(ASIHTTPRequest *)request
- (void)processGetTasksRequest:(ASIHTTPRequest *)request
{
- NSString *response = [request responseString];
- NSArray *tasksOverdue = [self deserializeXML:response
- forXPath:@"/hash/overdue/overdue"
- andClass:NSClassFromString(@"Task")];
- NSArray *tasksDueASAP = [self deserializeXML:response
- forXPath:@"/hash/due-asap/due-asap"
- andClass:NSClassFromString(@"Task")];
- NSArray *tasksDueToday = [self deserializeXML:response
- forXPath:@"/hash/due-today/due-today"
- andClass:NSClassFromString(@"Task")];
- NSArray *tasksDueTomorrow = [self deserializeXML:response
- forXPath:@"/hash/due-tomorrow/due-tomorrow"
- andClass:NSClassFromString(@"Task")];
- NSArray *tasksDueThisWeek = [self deserializeXML:response
- forXPath:@"/hash/due-this-week/due-this-week"
- andClass:NSClassFromString(@"Task")];
- NSArray *tasksDueNextWeek = [self deserializeXML:response
- forXPath:@"/hash/due-next-week/due-next-week"
- andClass:NSClassFromString(@"Task")];
- NSArray *tasksDueLater = [self deserializeXML:response
- forXPath:@"/hash/due-later/due-later"
- andClass:NSClassFromString(@"Task")];
+ NSData *response = [request responseData];
+ TBXML *tbxml = [TBXML tbxmlWithXMLData:response];
+ TBXMLElement *hash = tbxml.rootXMLElement;
+ Class klass = NSClassFromString(@"Task");
+
+ NSArray *tasksOverdue = [self deserializeXMLElement:[TBXML childElementNamed:@"overdue" parentElement:hash]
+ forXPath:@"overdue"
+ andClass:klass];
+ NSArray *tasksDueASAP = [self deserializeXMLElement:[TBXML childElementNamed:@"due-asap" parentElement:hash]
+ forXPath:@"due-asap"
+ andClass:klass];
+ NSArray *tasksDueToday = [self deserializeXMLElement:[TBXML childElementNamed:@"due-today" parentElement:hash]
+ forXPath:@"due-today"
+ andClass:klass];
+ NSArray *tasksDueTomorrow = [self deserializeXMLElement:[TBXML childElementNamed:@"due-tomorrow" parentElement:hash]
+ forXPath:@"due-tomorrow"
+ andClass:klass];
+ NSArray *tasksDueThisWeek = [self deserializeXMLElement:[TBXML childElementNamed:@"due-this-week" parentElement:hash]
+ forXPath:@"due-this-week"
+ andClass:klass];
+ NSArray *tasksDueNextWeek = [self deserializeXMLElement:[TBXML childElementNamed:@"due-next-week" parentElement:hash]
+ forXPath:@"due-next-week"
+ andClass:klass];
+ NSArray *tasksDueLater = [self deserializeXMLElement:[TBXML childElementNamed:@"due-later" parentElement:hash]
+ forXPath:@"due-later"
+ andClass:klass];
NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys:tasksOverdue, TASKS_OVERDUE_KEY,
tasksDueASAP, TASKS_DUE_ASAP_KEY,
View
11 Classes/Models/BaseEntity.h
@@ -33,7 +33,7 @@
//
#import <Foundation/Foundation.h>
-#import "TouchXML.h"
+#import "TBXML.h"
@interface BaseEntity : NSObject
{
@@ -42,15 +42,20 @@
NSDate *_createdAt;
NSDate *_updatedAt;
NSString *_name;
+ NSURL *_photoURL;
+ NSDateFormatter *_formatter;
}
@property (nonatomic) NSInteger objectId;
@property (nonatomic, retain) NSDate *createdAt;
@property (nonatomic, retain) NSDate *updatedAt;
@property (nonatomic, copy) NSString *name;
-@property (nonatomic, readonly) NSURL *photoURL;
+@property (nonatomic, retain) NSURL *photoURL;
@property (nonatomic, readonly) NSString *commentableTypeName;
+@property (nonatomic, retain) NSDateFormatter *formatter;
-- (id)initWithCXMLElement:(CXMLElement *)element;
++ (NSString *)stringValueForElement:(NSString *)elementName
+ parentElement:(TBXMLElement *)element;
+- (id)initWithTBXMLElement:(TBXMLElement *)element;
@end
View
71 Classes/Models/BaseEntity.m
@@ -33,6 +33,7 @@
//
#import "BaseEntity.h"
+#import "GTMNSString+HTML.h"
@implementation BaseEntity
@@ -40,61 +41,63 @@ @implementation BaseEntity
@synthesize objectId = _objectId;
@synthesize createdAt = _createdAt;
@synthesize updatedAt = _updatedAt;
+@synthesize formatter = _formatter;
+@synthesize photoURL = _photoURL;
-@dynamic photoURL;
@dynamic commentableTypeName;
#pragma mark -
+#pragma mark Class methods
+
++ (NSString *)stringValueForElement:(NSString *)elementName
+ parentElement:(TBXMLElement *)element
+{
+ TBXMLElement *attribute = [TBXML childElementNamed:elementName parentElement:element];
+ NSString *value = @"";
+ if (attribute != nil)
+ {
+ value = [[TBXML textForElement:attribute] gtm_stringByUnescapingFromHTML];
+ }
+ return value;
+}
+
+#pragma mark -
#pragma mark Init and dealloc
-- (id)initWithCXMLElement:(CXMLElement *)element
+- (id)initWithTBXMLElement:(TBXMLElement *)element
{
if (self = [super init])
{
- NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
- [formatter setDateFormat:@"yyyy-MM-dd'T'HH:mm:ss'Z'"];
- for(int counter = 0; counter < [element childCount]; ++counter)
- {
- id obj = [element childAtIndex:counter];
- NSString *nodeName = [obj name];
- if ([nodeName isEqualToString:@"id"])
- {
- _objectId = [[obj stringValue] intValue];
- }
- else if ([nodeName isEqualToString:@"created-at"])
- {
- _createdAt = [[formatter dateFromString:[obj stringValue]] retain];
- }
- else if ([nodeName isEqualToString:@"updated-at"])
- {
- _updatedAt = [[formatter dateFromString:[obj stringValue]] retain];
- }
- else if ([nodeName isEqualToString:@"name"])
- {
- _name = [[obj stringValue] copy];
- }
- }
- [formatter release];
+ self.formatter = [[[NSDateFormatter alloc] init] autorelease];
+ [self.formatter setDateFormat:@"yyyy-MM-dd'T'HH:mm:ss'Z'"];
+
+ NSString *value = [BaseEntity stringValueForElement:@"id" parentElement:element];
+ self.objectId = [value intValue];
+
+ value = [BaseEntity stringValueForElement:@"created-at" parentElement:element];
+ self.createdAt = [self.formatter dateFromString:value];
+
+ value = [BaseEntity stringValueForElement:@"updated-at" parentElement:element];
+ self.updatedAt = [self.formatter dateFromString:value];
+
+ self.name = [BaseEntity stringValueForElement:@"name" parentElement:element];
}
return self;
}
- (void)dealloc
{
- [_createdAt release];
- [_updatedAt release];
- [_name release];
+ self.formatter = nil;
+ self.createdAt = nil;
+ self.updatedAt = nil;
+ self.name = nil;
+ self.photoURL = nil;
[super dealloc];
}
#pragma mark -
#pragma mark Overridable properties
-- (NSURL *)photoURL
-{
- return nil;
-}
-
- (NSString *)commentableTypeName
{
return NSStringFromClass([self class]);
View
2 Classes/Models/Campaign.h
@@ -64,6 +64,6 @@
@property (nonatomic) double revenueTarget;
+ (NSString *)serverPath;
-- (id)initWithCXMLElement:(CXMLElement *)element;
+- (id)initWithTBXMLElement:(TBXMLElement *)element;
@end
View
88 Classes/Models/Campaign.m
@@ -53,84 +53,42 @@ + (NSString *)serverPath
return @"campaigns";
}
-- (id)initWithCXMLElement:(CXMLElement *)element
+- (id)initWithTBXMLElement:(TBXMLElement *)element
{
- if (self = [super initWithCXMLElement:element])
+ if (self = [super initWithTBXMLElement:element])
{
- NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
- [formatter setDateFormat:@"yyyy-MM-dd'T'HH:mm:ss'Z'"];
- for(int counter = 0; counter < [element childCount]; ++counter)
- {
- id obj = [element childAtIndex:counter];
- NSString *nodeName = [obj name];
- if ([nodeName isEqualToString:@"budget"])
- {
- _budget = [[obj stringValue] doubleValue];
- }
- else if ([nodeName isEqualToString:@"ends-on"])
- {
- if ([obj stringValue] != nil)
- {
- _endsOn = [[formatter dateFromString:[obj stringValue]] retain];
- }
- }
- else if ([nodeName isEqualToString:@"leads-count"])
- {
- _leadsCount = [[obj stringValue] intValue];
- }
- else if ([nodeName isEqualToString:@"objectives"])
- {
- _objectives = [[obj stringValue] copy];
- }
- else if ([nodeName isEqualToString:@"opportunities-count"])
- {
- _opportunitiesCount = [[obj stringValue] intValue];
- }
- else if ([nodeName isEqualToString:@"revenue"])
- {
- _revenue = [[obj stringValue] doubleValue];
- }
- else if ([nodeName isEqualToString:@"starts-on"])
- {
- if ([obj stringValue] != nil)
- {
- _startsOn = [[formatter dateFromString:[obj stringValue]] retain];
- }
- }
- else if ([nodeName isEqualToString:@"status"])
- {
- _status = [[obj stringValue] copy];
- }
- else if ([nodeName isEqualToString:@"target-conversion"])
- {
- _conversionTarget = [[obj stringValue] floatValue];
- }
- else if ([nodeName isEqualToString:@"target-leads"])
- {
- _leadsTarget = [[obj stringValue] intValue];
- }
- else if ([nodeName isEqualToString:@"target-revenue"])
- {
- _revenueTarget = [[obj stringValue] doubleValue];
- }
- }
- [formatter release];
+ self.budget = [[BaseEntity stringValueForElement:@"budget" parentElement:element] doubleValue];
+ self.endsOn = [self.formatter dateFromString:[BaseEntity stringValueForElement:@"ends-on"
+ parentElement:element]];
+ self.leadsCount = [[BaseEntity stringValueForElement:@"leads-count"
+ parentElement:element] intValue];
+ self.objectives = [BaseEntity stringValueForElement:@"objectives" parentElement:element];
+ self.opportunitiesCount = [[BaseEntity stringValueForElement:@"opportunities-count"
+ parentElement:element] intValue];
+ self.revenue = [[BaseEntity stringValueForElement:@"revenue"
+ parentElement:element] doubleValue];
+ self.startsOn = [self.formatter dateFromString:[BaseEntity stringValueForElement:@"starts-on"
+ parentElement:element]];
+ self.status = [BaseEntity stringValueForElement:@"status" parentElement:element];
+ self.conversionTarget = [[BaseEntity stringValueForElement:@"target-conversion" parentElement:element] floatValue];
+ self.leadsTarget = [[BaseEntity stringValueForElement:@"target-leads" parentElement:element] intValue];
+ self.revenueTarget = [[BaseEntity stringValueForElement:@"target-revenue" parentElement:element] doubleValue];
}
return self;
}
- (void)dealloc
{
- [_endsOn release];
- [_objectives release];
- [_startsOn release];
- [_status release];
+ self.endsOn = nil;
+ self.objectives = nil;
+ self.startsOn = nil;
+ self.status = nil;
[super dealloc];
}
- (NSString *)description
{
- return _status;
+ return self.status;
}
@end
View
2 Classes/Models/Comment.h
@@ -43,6 +43,6 @@
@property (nonatomic, copy) NSString *comment;
-- (id)initWithCXMLElement:(CXMLElement *)element;
+- (id)initWithTBXMLElement:(TBXMLElement *)element;
@end
View
16 Classes/Models/Comment.m
@@ -38,26 +38,18 @@ @implementation Comment
@synthesize comment = _comment;
-- (id)initWithCXMLElement:(CXMLElement *)element
+- (id)initWithTBXMLElement:(TBXMLElement *)element
{
- if (self = [super initWithCXMLElement:element])
+ if (self = [super initWithTBXMLElement:element])
{
- for(int counter = 0; counter < [element childCount]; ++counter)
- {
- id obj = [element childAtIndex:counter];
- NSString *nodeName = [obj name];
- if ([nodeName isEqualToString:@"comment"])
- {
- _comment = [[obj stringValue] copy];
- }
- }
+ self.comment = [BaseEntity stringValueForElement:@"comment" parentElement:element];
}
return self;
}
- (void)dealloc
{
- [_comment release];
+ self.comment = nil;
[super dealloc];
}
View
2 Classes/Models/CompanyAccount.h
@@ -54,6 +54,6 @@
@property (nonatomic, copy) NSString *website;
+ (NSString *)serverPath;
-- (id)initWithCXMLElement:(CXMLElement *)element;
+- (id)initWithTBXMLElement:(TBXMLElement *)element;
@end
View
53 Classes/Models/CompanyAccount.m
@@ -48,57 +48,34 @@ + (NSString *)serverPath
return @"accounts";
}
-- (id)initWithCXMLElement:(CXMLElement *)element
+- (id)initWithTBXMLElement:(TBXMLElement *)element
{
- if (self = [super initWithCXMLElement:element])
+ if (self = [super initWithTBXMLElement:element])
{
- for(int counter = 0; counter < [element childCount]; ++counter)
- {
- id obj = [element childAtIndex:counter];
- NSString *nodeName = [obj name];
- if ([nodeName isEqualToString:@"billing-address"])
- {
- _billingAddress = [[obj stringValue] copy];
- }
- else if ([nodeName isEqualToString:@"fax"])
- {
- _fax = [[obj stringValue] copy];
- }
- else if ([nodeName isEqualToString:@"phone"])
- {
- _phone = [[obj stringValue] copy];
- }
- else if ([nodeName isEqualToString:@"shipping-address"])
- {
- _shippingAddress = [[obj stringValue] copy];
- }
- else if ([nodeName isEqualToString:@"toll-free-phone"])
- {
- _tollFreePhone = [[obj stringValue] copy];
- }
- else if ([nodeName isEqualToString:@"website"])
- {
- _website = [[obj stringValue] copy];
- }
- }
+ self.billingAddress = [BaseEntity stringValueForElement:@"billing-address" parentElement:element];
+ self.fax = [BaseEntity stringValueForElement:@"fax" parentElement:element];
+ self.phone = [BaseEntity stringValueForElement:@"phone" parentElement:element];
+ self.shippingAddress = [BaseEntity stringValueForElement:@"shipping-address" parentElement:element];
+ self.tollFreePhone = [BaseEntity stringValueForElement:@"toll-free-phone" parentElement:element];
+ self.website = [BaseEntity stringValueForElement:@"website" parentElement:element];
}
return self;
}
- (void)dealloc
{
- [_billingAddress release];
- [_fax release];
- [_phone release];
- [_shippingAddress release];
- [_tollFreePhone release];
- [_website release];
+ self.billingAddress = nil;
+ self.fax = nil;
+ self.phone = nil;
+ self.shippingAddress = nil;
+ self.tollFreePhone = nil;
+ self.website = nil;
[super dealloc];
}
- (NSString *)description
{
- return _website;
+ return self.website;
}
#pragma mark -
View
4 Classes/Models/Contact.h
@@ -56,8 +56,6 @@
NSString *_twitter;
NSDate *_birthDate;
BOOL _doNotCall;
-
- NSURL *_photoURL;
}
@property (nonatomic, copy) NSString *address;
@@ -82,6 +80,6 @@
+ (NSString *)serverPath;
+ (NSArray *)displayedProperties;
-- (id)initWithCXMLElement:(CXMLElement *)element;
+- (id)initWithTBXMLElement:(TBXMLElement *)element;
@end
View
200 Classes/Models/Contact.m
@@ -102,102 +102,41 @@ + (NSArray *)displayedProperties
#pragma mark -
#pragma mark Init and dealloc
-- (id)initWithCXMLElement:(CXMLElement *)element
+- (id)initWithTBXMLElement:(TBXMLElement *)element
{
- if (self = [super initWithCXMLElement:element])
+ if (self = [super initWithTBXMLElement:element])
{
- _photoURL = nil;
- for(int counter = 0; counter < [element childCount]; ++counter)
- {
- id obj = [element childAtIndex:counter];
- NSString *nodeName = [obj name];
- if ([nodeName isEqualToString:@"address"])
- {
- _address = [[obj stringValue] copy];
- }
- else if ([nodeName isEqualToString:@"alt-email"])
- {
- _altEmail = [[obj stringValue] copy];
- }
- else if ([nodeName isEqualToString:@"blog"])
- {
- _blog = [[obj stringValue] copy];
- }
- else if ([nodeName isEqualToString:@"born-on"])
- {
- if ([obj stringValue] != nil)
- {
- NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
- [formatter setDateFormat:@"yyyy-MM-dd'T'HH:mm:ss'Z'"];
- _birthDate = [[formatter dateFromString:[obj stringValue]] retain];
- [formatter release];
- }
- }
- else if ([nodeName isEqualToString:@"department"])
- {
- _department = [[obj stringValue] copy];
- }
- else if ([nodeName isEqualToString:@"do-not-call"])
- {
- _doNotCall = [[obj stringValue] isEqualToString:@"true"];
- }
- else if ([nodeName isEqualToString:@"email"])
- {
- _email = [[obj stringValue] copy];
- }
- else if ([nodeName isEqualToString:@"facebook"])
- {
- _facebook = [[obj stringValue] copy];
- }
- else if ([nodeName isEqualToString:@"fax"])
- {
- _fax = [[obj stringValue] copy];
- }
- else if ([nodeName isEqualToString:@"first-name"])
- {
- _firstName = [[obj stringValue] copy];
- }
- else if ([nodeName isEqualToString:@"last-name"])
- {
- _lastName = [[obj stringValue] copy];
- }
- else if ([nodeName isEqualToString:@"linkedin"])
- {
- _linkedIn = [[obj stringValue] copy];
- }
- else if ([nodeName isEqualToString:@"mobile"])
- {
- _mobile = [[obj stringValue] copy];
- }
- else if ([nodeName isEqualToString:@"phone"])
- {
- _phone = [[obj stringValue] copy];
- }
- else if ([nodeName isEqualToString:@"source"])
- {
- _source = [[obj stringValue] copy];
- }
- else if ([nodeName isEqualToString:@"title"])
- {
- _title = [[obj stringValue] copy];
- }
- else if ([nodeName isEqualToString:@"twitter"])
- {
- _twitter = [[obj stringValue] copy];
- }
- }
+ self.photoURL = nil;
+ self.address = [BaseEntity stringValueForElement:@"address" parentElement:element];
+ self.altEmail = [BaseEntity stringValueForElement:@"alt-email" parentElement:element];
+ self.blog = [BaseEntity stringValueForElement:@"blog" parentElement:element];
+ self.birthDate = [self.formatter dateFromString:[BaseEntity stringValueForElement:@"born-on"
+ parentElement:element]];
+ self.department = [BaseEntity stringValueForElement:@"department" parentElement:element];
+ self.doNotCall = [[BaseEntity stringValueForElement:@"do-not-call" parentElement:element] isEqualToString:@"true"];
+ self.email = [BaseEntity stringValueForElement:@"email" parentElement:element];
+ self.facebook = [BaseEntity stringValueForElement:@"facebook" parentElement:element];
+ self.fax = [BaseEntity stringValueForElement:@"fax" parentElement:element];
+ self.firstName = [BaseEntity stringValueForElement:@"first-name" parentElement:element];
+ self.lastName = [BaseEntity stringValueForElement:@"last-name" parentElement:element];
+ self.linkedIn = [BaseEntity stringValueForElement:@"linkedin" parentElement:element];
+ self.mobile = [BaseEntity stringValueForElement:@"mobile" parentElement:element];
+ self.phone = [BaseEntity stringValueForElement:@"phone" parentElement:element];
+ self.source = [BaseEntity stringValueForElement:@"source" parentElement:element];
+ self.title = [BaseEntity stringValueForElement:@"title" parentElement:element];
+ self.twitter = [BaseEntity stringValueForElement:@"twitter" parentElement:element];
NSString *serverURL = [[NSUserDefaults standardUserDefaults] stringForKey:PREFERENCES_SERVER_URL];
NSString *defaultImage = [NSString stringWithFormat:@"%@/images/avatar.jpg", serverURL];
- _photoURL = [[NSURL alloc] initWithString:defaultImage];
+ self.photoURL = [[NSURL alloc] initWithString:defaultImage];
- if (_email != nil)
+ if (self.email != nil)
{
- NSString *emailHash = [_email md5];
+ NSString *emailHash = [self.email md5];
NSString *base = @"http://www.gravatar.com/avatar";
- defaultImage = [_photoURL cacheKey];
+ defaultImage = [self.photoURL cacheKey];
NSString *stringURL = [NSString stringWithFormat:@"%@/%@.png?d=%@&s=50", base, emailHash, defaultImage];
- _photoURL = [[NSURL alloc] initWithString:stringURL];
+ self.photoURL = [[NSURL alloc] initWithString:stringURL];
}
}
return self;
@@ -205,23 +144,23 @@ - (id)initWithCXMLElement:(CXMLElement *)element
- (void)dealloc
{
- [_photoURL release];
- [_address release];
- [_altEmail release];
- [_blog release];
- [_department release];
- [_email release];
- [_facebook release];
- [_fax release];
- [_firstName release];
- [_lastName release];
- [_linkedIn release];
- [_mobile release];
- [_phone release];
- [_source release];
- [_title release];
- [_twitter release];
- [_birthDate release];
+ self.photoURL = nil;
+ self.address = nil;
+ self.altEmail = nil;
+ self.blog = nil;
+ self.department = nil;
+ self.email = nil;
+ self.facebook = nil;
+ self.fax = nil;
+ self.firstName = nil;
+ self.lastName = nil;
+ self.linkedIn = nil;
+ self.mobile = nil;
+ self.phone = nil;
+ self.source = nil;
+ self.title = nil;
+ self.twitter = nil;
+ self.birthDate = nil;
[super dealloc];
}
@@ -231,33 +170,33 @@ - (void)dealloc
- (NSString *)description
{
NSMutableString *result = [[NSMutableString alloc] init];
- if ([_title length] > 0)
+ if ([self.title length] > 0)
{
- [result appendString:_title];
+ [result appendString:self.title];
}
- if ([_department length] > 0)
+ if ([self.department length] > 0)
{
if ([result length] > 0)
{
[result appendString:@" - "];
}
- [result appendString:_department];
+ [result appendString:self.department];
}
- if ([_phone length] > 0)
+ if ([self.phone length] > 0)
{
if ([result length] > 0)
{
[result appendString:@" - "];
}
- [result appendString:_phone];
+ [result appendString:self.phone];
}
- if ([_email length] > 0)
+ if ([self.email length] > 0)
{
if ([result length] > 0)
{
[result appendString:@" - "];
}
- [result appendString:_email];
+ [result appendString:self.email];
}
return [result autorelease];
@@ -265,7 +204,7 @@ - (NSString *)description
- (NSString *)name
{
- return [NSString stringWithFormat:@"%@ %@", _firstName, _lastName];
+ return [NSString stringWithFormat:@"%@ %@", self.firstName, self.lastName];
}
#pragma mark -
@@ -274,19 +213,27 @@ - (NSString *)name
- (ABRecordRef)person
{
ABRecordRef person = ABPersonCreate();
- ABRecordSetValue(person, kABPersonFirstNameProperty, _firstName, nil);
- ABRecordSetValue(person, kABPersonLastNameProperty, _lastName, nil);
- ABRecordSetValue(person, kABPersonJobTitleProperty, _title, nil);
- ABRecordSetValue(person, kABPersonDepartmentProperty, _department, nil);
+ ABRecordSetValue(person, kABPersonFirstNameProperty, self.firstName, nil);
+ ABRecordSetValue(person, kABPersonLastNameProperty, self.lastName, nil);
- ABRecordSetValue(person, kABPersonBirthdayProperty, [_birthDate stringWithDateFormattedWithCurrentLocale], nil);
+ if ([self.title length] > 0)
+ {
+ ABRecordSetValue(person, kABPersonJobTitleProperty, self.title, nil);
+ }
- setPersonPropertyValue(person, kABPersonPhoneProperty, kABPersonPhoneMobileLabel, _mobile);
- setPersonPropertyValue(person, kABPersonPhoneProperty, kABPersonPhoneMainLabel, _phone);
- setPersonPropertyValue(person, kABPersonPhoneProperty, kABPersonPhoneWorkFAXLabel, _fax);
- setPersonPropertyValue(person, kABPersonURLProperty, kABPersonHomePageLabel, _blog);
- setPersonPropertyValue(person, kABPersonEmailProperty, kABWorkLabel, _email);
- setPersonPropertyValue(person, kABPersonEmailProperty, kABHomeLabel, _altEmail);
+ if ([self.department length] > 0)
+ {
+ ABRecordSetValue(person, kABPersonDepartmentProperty, self.department, nil);
+ }
+
+ ABRecordSetValue(person, kABPersonBirthdayProperty, [self.birthDate stringWithDateFormattedWithCurrentLocale], nil);
+
+ setPersonPropertyValue(person, kABPersonPhoneProperty, kABPersonPhoneMobileLabel, self.mobile);
+ setPersonPropertyValue(person, kABPersonPhoneProperty, kABPersonPhoneMainLabel, self.phone);
+ setPersonPropertyValue(person, kABPersonPhoneProperty, kABPersonPhoneWorkFAXLabel, self.fax);
+ setPersonPropertyValue(person, kABPersonURLProperty, kABPersonHomePageLabel, self.blog);
+ setPersonPropertyValue(person, kABPersonEmailProperty, kABWorkLabel, self.email);
+ setPersonPropertyValue(person, kABPersonEmailProperty, kABHomeLabel, self.altEmail);
NSString *key = [self.photoURL cacheKey];
UIImage *image = [[AKOImageCache sharedAKOImageCache] imageForKey:key];
@@ -301,9 +248,4 @@ - (ABRecordRef)person
return person;
}
-- (NSURL *)photoURL
-{
- return _photoURL;
-}
-
@end
View
2 Classes/Models/Lead.h
@@ -46,6 +46,6 @@
@property (nonatomic, copy) NSString *referredBy;
+ (NSString *)serverPath;
-- (id)initWithCXMLElement:(CXMLElement *)element;
+- (id)initWithTBXMLElement:(TBXMLElement *)element;
@end
View
25 Classes/Models/Lead.m
@@ -44,37 +44,26 @@ + (NSString *)serverPath
return @"leads";
}
-- (id)initWithCXMLElement:(CXMLElement *)element
+- (id)initWithTBXMLElement:(TBXMLElement *)element
{
- if (self = [super initWithCXMLElement:element])
+ if (self = [super initWithTBXMLElement:element])
{
- for(int counter = 0; counter < [element childCount]; ++counter)
- {
- id obj = [element childAtIndex:counter];
- NSString *nodeName = [obj name];
- if ([nodeName isEqualToString:@"status"])
- {
- _status = [[obj stringValue] copy];
- }
- else if ([nodeName isEqualToString:@"referred-by"])
- {
- _referredBy = [[obj stringValue] copy];
- }
- }
+ self.status = [BaseEntity stringValueForElement:@"status" parentElement:element];
+ self.referredBy = [BaseEntity stringValueForElement:@"referred-by" parentElement:element];
}
return self;
}
- (void)dealloc
{
- [_status release];
- [_referredBy release];
+ self.status = nil;
+ self.referredBy = nil;
[super dealloc];
}
- (NSString *)description
{
- return _status;
+ return self.status;
}
@end
View
2 Classes/Models/Opportunity.h
@@ -54,6 +54,6 @@
@property (nonatomic, copy) NSString *stage;
+ (NSString *)serverPath;
-- (id)initWithCXMLElement:(CXMLElement *)element;
+- (id)initWithTBXMLElement:(TBXMLElement *)element;
@end
View
54 Classes/Models/Opportunity.m
@@ -48,60 +48,32 @@ + (NSString *)serverPath
return @"opportunities";
}
-- (id)initWithCXMLElement:(CXMLElement *)element
+- (id)initWithTBXMLElement:(TBXMLElement *)element
{
- if (self = [super initWithCXMLElement:element])
+ if (self = [super initWithTBXMLElement:element])
{
- for(int counter = 0; counter < [element childCount]; ++counter)
- {
- id obj = [element childAtIndex:counter];
- NSString *nodeName = [obj name];
- if ([nodeName isEqualToString:@"amount"])
- {
- _amount = [[obj stringValue] doubleValue];
- }
- else if ([nodeName isEqualToString:@"discount"])
- {
- _discount = [[obj stringValue] doubleValue];
- }
- else if ([nodeName isEqualToString:@"probability"])
- {
- _probability = [[obj stringValue] intValue];
- }
- else if ([nodeName isEqualToString:@"closes-on"])
- {
- if ([obj stringValue] != nil)
- {
- NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
- [formatter setDateFormat:@"yyyy-MM-dd'T'HH:mm:ss'Z'"];
- _closingDate = [[formatter dateFromString:[obj stringValue]] retain];
- [formatter release];
- }
- }
- else if ([nodeName isEqualToString:@"source"])
- {
- _source = [[obj stringValue] copy];
- }
- else if ([nodeName isEqualToString:@"stage"])
- {
- _stage = [[obj stringValue] copy];
- }
- }
+ self.amount = [[BaseEntity stringValueForElement:@"amount" parentElement:element] doubleValue];
+ self.discount = [[BaseEntity stringValueForElement:@"discount" parentElement:element] doubleValue];
+ self.probability = [[BaseEntity stringValueForElement:@"probability" parentElement:element] intValue];
+ self.source = [BaseEntity stringValueForElement:@"source" parentElement:element];
+ self.stage = [BaseEntity stringValueForElement:@"stage" parentElement:element];
+ self.closingDate = [self.formatter dateFromString:[BaseEntity stringValueForElement:@"closes-on"
+ parentElement:element]];
}
return self;
}
- (void)dealloc
{
- [_closingDate release];
- [_source release];
- [_stage release];
+ self.closingDate = nil;
+ self.source = nil;
+ self.stage = nil;
[super dealloc];
}
- (NSString *)description
{
- return _stage;
+ return self.stage;
}
@end
View
2 Classes/Models/Task.h
@@ -47,6 +47,6 @@
@property (nonatomic, copy) NSString *category;
@property (nonatomic, copy) NSString *bucket;
-- (id)initWithCXMLElement:(CXMLElement *)element;
+- (id)initWithTBXMLElement:(TBXMLElement *)element;
@end
View
37 Classes/Models/Task.m
@@ -40,42 +40,23 @@ @implementation Task
@synthesize category = _category;
@synthesize bucket = _bucket;
-- (id)initWithCXMLElement:(CXMLElement *)element
+- (id)initWithTBXMLElement:(TBXMLElement *)element
{
- if (self = [super initWithCXMLElement:element])
+ if (self = [super initWithTBXMLElement:element])
{
- for(int counter = 0; counter < [element childCount]; ++counter)
- {
- id obj = [element childAtIndex:counter];
- NSString *nodeName = [obj name];
- if ([nodeName isEqualToString:@"category"])
- {
- _category = [[obj stringValue] copy];
- }
- else if ([nodeName isEqualToString:@"bucket"])
- {
- _bucket = [[obj stringValue] copy];
- }
- else if ([nodeName isEqualToString:@"due-at"])
- {
- if ([obj stringValue] != nil)
- {
- NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
- [formatter setDateFormat:@"yyyy-MM-dd'T'HH:mm:ss'Z'"];
- _dueDate = [[formatter dateFromString:[obj stringValue]] retain];
- [formatter release];
- }
- }
- }
+ self.category = [BaseEntity stringValueForElement:@"category" parentElement:element];
+ self.bucket = [BaseEntity stringValueForElement:@"bucket" parentElement:element];
+ self.dueDate = [self.formatter dateFromString:[BaseEntity stringValueForElement:@"due-at"
+ parentElement:element]];
}
return self;
}
- (void)dealloc
{
- [_bucket release];
- [_dueDate release];
- [_category release];
+ self.bucket = nil;
+ self.dueDate = nil;
+ self.category = nil;
[super dealloc];
}
View
2 Classes/Models/User.h
@@ -69,6 +69,6 @@
@property (nonatomic, copy) NSString *username;
@property (nonatomic, copy) NSString *yahoo;
-- (id)initWithCXMLElement:(CXMLElement *)element;
+- (id)initWithTBXMLElement:(TBXMLElement *)element;
@end
View
102 Classes/Models/User.m
@@ -51,92 +51,48 @@ @implementation User
@synthesize username = _username;
@synthesize yahoo = _yahoo;
-- (id)initWithCXMLElement:(CXMLElement *)element
+- (id)initWithTBXMLElement:(TBXMLElement *)element
{
- if (self = [super initWithCXMLElement:element])
+ if (self = [super initWithTBXMLElement:element])
{
- for(int counter = 0; counter < [element childCount]; ++counter)
- {
- id obj = [element childAtIndex:counter];
- NSString *nodeName = [obj name];
- if ([nodeName isEqualToString:@"admin"])
- {
- _admin = [[obj stringValue] isEqualToString:@"true"];
- }
- else if ([nodeName isEqualToString:@"alt-email"])
- {
- _altEmail = [[obj stringValue] copy];
- }
- else if ([nodeName isEqualToString:@"company"])
- {
- _company = [[obj stringValue] copy];
- }
- else if ([nodeName isEqualToString:@"email"])
- {
- _email = [[obj stringValue] copy];
- }
- else if ([nodeName isEqualToString:@"first-name"])
- {
- _firstName = [[obj stringValue] copy];
- }
- else if ([nodeName isEqualToString:@"google"])
- {
- _google = [[obj stringValue] copy];
- }
- else if ([nodeName isEqualToString:@"last-name"])
- {
- _lastName = [[obj stringValue] copy];
- }
- else if ([nodeName isEqualToString:@"mobile"])
- {
- _mobile = [[obj stringValue] copy];
- }
- else if ([nodeName isEqualToString:@"phone"])
- {
- _phone = [[obj stringValue] copy];
- }
- else if ([nodeName isEqualToString:@"skype"])
- {
- _skype = [[obj stringValue] copy];
- }
- else if ([nodeName isEqualToString:@"title"])
- {
- _title = [[obj stringValue] copy];
- }
- else if ([nodeName isEqualToString:@"username"])
- {
- _username = [[obj stringValue] copy];
- }
- else if ([nodeName isEqualToString:@"yahoo"])
- {
- _yahoo = [[obj stringValue] copy];
- }
- }
+ self.admin = [[BaseEntity stringValueForElement:@"admin" parentElement:element] isEqualToString:@"true"];
+ self.altEmail = [BaseEntity stringValueForElement:@"alt-email" parentElement:element];
+ self.company = [BaseEntity stringValueForElement:@"company" parentElement:element];
+ self.email = [BaseEntity stringValueForElement:@"email" parentElement:element];
+ self.firstName = [BaseEntity stringValueForElement:@"first-name" parentElement:element];
+ self.google = [BaseEntity stringValueForElement:@"google" parentElement:element];
+ self.lastName = [BaseEntity stringValueForElement:@"last-name" parentElement:element];
+ self.mobile = [BaseEntity stringValueForElement:@"mobile" parentElement:element];
+ self.phone = [BaseEntity stringValueForElement:@"phone" parentElement:element];
+ self.skype = [BaseEntity stringValueForElement:@"skype" parentElement:element];
+ self.title = [BaseEntity stringValueForElement:@"title" parentElement:element];
+ self.username = [BaseEntity stringValueForElement:@"username" parentElement:element];
+ self.yahoo = [BaseEntity stringValueForElement:@"yahoo" parentElement:element];
}
return self;
}
- (void)dealloc
{
- [_aim release];
- [_altEmail release];
- [_company release];
- [_email release];
- [_firstName release];
- [_google release];
- [_lastName release];
- [_mobile release];
- [_phone release];
- [_skype release];
- [_title release];
- [_username release];
- [_yahoo release];
+ self.aim = nil;
+ self.altEmail = nil;
+ self.company = nil;
+ self.email = nil;
+ self.firstName = nil;
+ self.google = nil;
+ self.lastName = nil;
+ self.mobile = nil;
+ self.phone = nil;
+ self.skype = nil;
+ self.title = nil;
+ self.username = nil;
+ self.yahoo = nil;
[super dealloc];
}
- (NSString *)description
{
- return [NSString stringWithFormat:@"%@ %@", _firstName, _lastName];
+ return [NSString stringWithFormat:@"%@ %@", self.firstName, self.lastName];
}
@end
View
166 Externals/Google Toolbox for Mac/GTMDefines.h
@@ -0,0 +1,166 @@
+//
+// 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.
+//
+
+// ============================================================================
+
+// ----------------------------------------------------------------------------
+// CPP symbols that can be overridden in a prefix to control how the toolbox
+// is compiled.
+// ----------------------------------------------------------------------------
+
+
+// GTMHTTPFetcher will support logging by default but only hook its input
+// stream support for logging when requested. You can control the inclusion of
+// the code by providing your own definitions for these w/in a prefix header.
+//
+#ifndef GTM_HTTPFETCHER_ENABLE_LOGGING
+# define GTM_HTTPFETCHER_ENABLE_LOGGING 1
+#endif // GTM_HTTPFETCHER_ENABLE_LOGGING
+#ifndef GTM_HTTPFETCHER_ENABLE_INPUTSTREAM_LOGGING
+# define GTM_HTTPFETCHER_ENABLE_INPUTSTREAM_LOGGING 0
+#endif // GTM_HTTPFETCHER_ENABLE_INPUTSTREAM_LOGGING
+
+
+// _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 conditon 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
+
+// Declared here so that it can easily be used for logging tracking if
+// necessary. See GTMUnitTestDevLog.h for details.
+@class NSString;
+extern void _GTMUnittestDevLog(NSString *format, ...);
+
+#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 stringWithCString:__PRETTY_FUNCTION__ encoding:NSUTF8StringEncoding] \
+ file:[NSString stringWithCString:__FILE__ encoding:NSUTF8StringEncoding] \
+ 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
+// _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
+// 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 // _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.
+#include <TargetConditionals.h>
+#if TARGET_OS_IPHONE // iPhone SDK
+ // For iPhone specific stuff
+ #define GTM_IPHONE_SDK 1
+#else
+ // For MacOS specific stuff
+ #define GTM_MACOS_SDK 1
+#endif
+
+// To simplify support for 64bit (and Leopard in general), we provide the type
+// defines for non Leopard SDKs
+#if MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_4
+ // NSInteger/NSUInteger and Max/Mins
+ #ifndef NSINTEGER_DEFINED
+ #if __LP64__ || NS_BUILD_32_LIKE_64
+ typedef long NSInteger;
+ typedef unsigned long NSUInteger;
+ #else
+ typedef int NSInteger;
+ typedef unsigned int NSUInteger;
+ #endif
+ #define NSIntegerMax LONG_MAX
+ #define NSIntegerMin LONG_MIN
+ #define NSUIntegerMax ULONG_MAX
+ #define NSINTEGER_DEFINED 1
+ #endif // NSINTEGER_DEFINED
+ // CGFloat
+ #ifndef CGFLOAT_DEFINED
+ #if defined(__LP64__) && __LP64__
+ // This really is an untested path (64bit on Tiger?)
+ typedef double CGFloat;
+ #define CGFLOAT_MIN DBL_MIN
+ #define CGFLOAT_MAX DBL_MAX
+ #define CGFLOAT_IS_DOUBLE 1
+ #else /* !defined(__LP64__) || !__LP64__ */
+ typedef float CGFloat;
+ #define CGFLOAT_MIN FLT_MIN
+ #define CGFLOAT_MAX FLT_MAX
+ #define CGFLOAT_IS_DOUBLE 0
+ #endif /* !defined(__LP64__) || !__LP64__ */
+ #define CGFLOAT_DEFINED 1
+ #endif // CGFLOAT_DEFINED
+#endif // MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_4
View
66 Externals/Google Toolbox for Mac/GTMNSString+HTML.h
@@ -0,0 +1,66 @@
+//
+// GTMNSString+HTML.h
+// Dealing with NSStrings that contain HTML
+//
+// 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 NSStrings containing HTML
+@interface NSString (GTMNSStringHTMLAdditions)
+
+/// Get a string where internal characters that need escaping for HTML are escaped
+//
+/// For example, '&' become '&amp;'. This will only cover characters from table
+/// A.2.2 of http://www.w3.org/TR/xhtml1/dtds.html#a_dtd_Special_characters
+/// which is what you want for a unicode encoded webpage. If you have a ascii
+/// or non-encoded webpage, please use stringByEscapingAsciiHTML which will
+/// encode all characters.
+///
+/// For obvious reasons this call is only safe once.
+//
+// Returns:
+// Autoreleased NSString
+//
+- (NSString *)gtm_stringByEscapingForHTML;
+
+/// Get a string where internal characters that need escaping for HTML are escaped
+//
+/// For example, '&' become '&amp;'
+/// All non-mapped characters (unicode that don't have a &keyword; mapping)
+/// will be converted to the appropriate &#xxx; value. If your webpage is
+/// unicode encoded (UTF16 or UTF8) use stringByEscapingHTML instead as it is
+/// faster, and produces less bloated and more readable HTML (as long as you
+/// are using a unicode compliant HTML reader).
+///
+/// For obvious reasons this call is only safe once.
+//
+// Returns:
+// Autoreleased NSString
+//
+- (NSString *)gtm_stringByEscapingForAsciiHTML;
+
+/// Get a string where internal characters that are escaped for HTML are unescaped
+//
+/// For example, '&amp;' becomes '&'
+/// Handles &#32; and &#x32; cases as well
+///
+// Returns:
+// Autoreleased NSString
+//
+- (NSString *)gtm_stringByUnescapingFromHTML;
+
+@end
View
522 Externals/Google Toolbox for Mac/GTMNSString+HTML.m
@@ -0,0 +1,522 @@
+//
+// GTMNSString+HTML.m
+// Dealing with NSStrings that contain HTML
+//
+// 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 "GTMDefines.h"
+#import "GTMNSString+HTML.h"
+
+typedef struct {
+ NSString *escapeSequence;
+ unichar uchar;
+} HTMLEscapeMap;
+
+// Taken from http://www.w3.org/TR/xhtml1/dtds.html#a_dtd_Special_characters
+// Ordered by uchar lowest to highest for bsearching
+static HTMLEscapeMap gAsciiHTMLEscapeMap[] = {
+ // A.2.2. Special characters
+ { @"&quot;", 34 },
+ { @"&amp;", 38 },
+ { @"&apos;", 39 },
+ { @"&lt;", 60 },
+ { @"&gt;", 62 },
+
+ // A.2.1. Latin-1 characters
+ { @"&nbsp;", 160 },
+ { @"&iexcl;", 161 },
+ { @"&cent;", 162 },
+ { @"&pound;", 163 },
+ { @"&curren;", 164 },
+ { @"&yen;", 165 },
+ { @"&brvbar;", 166 },
+ { @"&sect;", 167 },
+ { @"&uml;", 168 },
+ { @"&copy;", 169 },
+ { @"&ordf;", 170 },
+ { @"&laquo;", 171 },
+ { @"&not;", 172 },
+ { @"&shy;", 173 },
+ { @"&reg;", 174 },
+ { @"&macr;", 175 },
+ { @"&deg;", 176 },
+ { @"&plusmn;", 177 },
+ { @"&sup2;", 178 },
+ { @"&sup3;", 179 },
+ { @"&acute;", 180 },
+ { @"&micro;", 181 },
+ { @"&para;", 182 },
+ { @"&middot;", 183 },
+ { @"&cedil;", 184 },
+ { @"&sup1;", 185 },
+ { @"&ordm;", 186 },
+ { @"&raquo;", 187 },
+ { @"&frac14;", 188 },
+ { @"&frac12;", 189 },
+ { @"&frac34;", 190 },
+ { @"&iquest;", 191 },
+ { @"&Agrave;", 192 },
+ { @"&Aacute;", 193 },
+ { @"&Acirc;", 194 },
+ { @"&Atilde;", 195 },
+ { @"&Auml;", 196 },
+ { @"&Aring;", 197 },
+ { @"&AElig;", 198 },
+ { @"&Ccedil;", 199 },
+ { @"&Egrave;", 200 },
+ { @"&Eacute;", 201 },
+ { @"&Ecirc;", 202 },
+ { @"&Euml;", 203 },
+ { @"&Igrave;", 204 },
+ { @"&Iacute;", 205 },
+ { @"&Icirc;", 206 },
+ { @"&Iuml;", 207 },
+ { @"&ETH;", 208 },
+ { @"&Ntilde;", 209 },
+ { @"&Ograve;", 210 },
+ { @"&Oacute;", 211 },
+ { @"&Ocirc;", 212 },
+ { @"&Otilde;", 213 },
+ { @"&Ouml;", 214 },
+ { @"&times;", 215 },
+ { @"&Oslash;", 216 },
+ { @"&Ugrave;", 217 },
+ { @"&Uacute;", 218 },
+ { @"&Ucirc;", 219 },
+ { @"&Uuml;", 220 },
+ { @"&Yacute;", 221 },
+ { @"&THORN;", 222 },
+ { @"&szlig;", 223 },
+ { @"&agrave;", 224 },
+ { @"&aacute;", 225 },
+ { @"&acirc;", 226 },
+ { @"&atilde;", 227 },
+ { @"&auml;", 228 },
+ { @"&aring;", 229 },
+ { @"&aelig;", 230 },
+ { @"&ccedil;", 231 },
+ { @"&egrave;", 232 },
+ { @"&eacute;", 233 },
+ { @"&ecirc;", 234 },
+ { @"&euml;", 235 },
+ { @"&igrave;", 236 },
+ { @"&iacute;", 237 },
+ { @"&icirc;", 238 },
+ { @"&iuml;", 239 },
+ { @"&eth;", 240 },
+ { @"&ntilde;", 241 },
+ { @"&ograve;", 242 },
+ { @"&oacute;", 243 },
+ { @"&ocirc;", 244 },
+ { @"&otilde;", 245 },
+ { @"&ouml;", 246 },
+ { @"&divide;", 247 },
+ { @"&oslash;", 248 },
+ { @"&ugrave;", 249 },
+ { @"&uacute;", 250 },
+ { @"&ucirc;", 251 },
+ { @"&uuml;", 252 },
+ { @"&yacute;", 253 },
+ { @"&thorn;", 254 },
+ { @"&yuml;", 255 },
+
+ // A.2.2. Special characters cont'd
+ { @"&OElig;", 338 },
+ { @"&oelig;", 339 },
+ { @"&Scaron;", 352 },
+ { @"&scaron;", 353 },
+ { @"&Yuml;", 376 },
+
+ // A.2.3. Symbols
+ { @"&fnof;", 402 },
+
+ // A.2.2. Special characters cont'd
+ { @"&circ;", 710 },
+ { @"&tilde;", 732 },
+
+ // A.2.3. Symbols cont'd
+ { @"&Alpha;", 913 },
+ { @"&Beta;", 914 },
+ { @"&Gamma;", 915 },
+ { @"&Delta;", 916 },
+ { @"&Epsilon;", 917 },
+ { @"&Zeta;", 918 },
+ { @"&Eta;", 919 },
+ { @"&Theta;", 920 },
+ { @"&Iota;", 921 },
+ { @"&Kappa;", 922 },
+ { @"&Lambda;", 923 },
+ { @"&Mu;", 924 },
+ { @"&Nu;", 925 },
+ { @"&Xi;", 926 },
+ { @"&Omicron;", 927 },
+ { @"&Pi;", 928 },
+ { @"&Rho;", 929 },
+ { @"&Sigma;", 931 },
+ { @"&Tau;", 932 },
+ { @"&Upsilon;", 933 },
+ { @"&Phi;", 934 },
+ { @"&Chi;", 935 },
+ { @"&Psi;", 936 },
+ { @"&Omega;", 937 },
+ { @"&alpha;", 945 },
+ { @"&beta;", 946 },
+ { @"&gamma;", 947 },
+ { @"&delta;", 948 },
+ { @"&epsilon;", 949 },
+ { @"&zeta;", 950 },
+ { @"&eta;", 951 },
+ { @"&theta;", 952 },
+ { @"&iota;", 953 },
+ { @"&kappa;", 954 },
+ { @"&lambda;", 955 },
+ { @"&mu;", 956 },
+ { @"&nu;", 957 },
+ { @"&xi;", 958 },
+ { @"&omicron;", 959 },
+ { @"&pi;", 960 },
+ { @"&rho;", 961 },
+ { @"&sigmaf;", 962 },
+ { @"&sigma;", 963 },
+ { @"&tau;", 964 },
+ { @"&upsilon;", 965 },
+ { @"&phi;", 966 },
+ { @"&chi;", 967 },
+ { @"&psi;", 968 },
+ { @"&omega;", 969 },
+ { @"&thetasym;", 977 },
+ { @"&upsih;", 978 },
+ { @"&piv;", 982 },
+
+ // A.2.2. Special characters cont'd
+ { @"&ensp;", 8194 },
+ { @"&emsp;", 8195 },
+ { @"&thinsp;", 8201 },
+ { @"&zwnj;", 8204 },
+ { @"&zwj;", 8205 },
+ { @"&lrm;", 8206 },
+ { @"&rlm;", 8207 },
+ { @"&ndash;", 8211 },
+ { @"&mdash;", 8212 },
+ { @"&lsquo;", 8216 },
+ { @"&rsquo;", 8217 },
+ { @"&sbquo;", 8218 },
+ { @"&ldquo;", 8220 },
+ { @"&rdquo;", 8221 },
+ { @"&bdquo;", 8222 },
+ { @"&dagger;", 8224 },
+ { @"&Dagger;", 8225 },
+ // A.2.3. Symbols cont'd
+ { @"&bull;", 8226 },
+ { @"&hellip;", 8230 },
+
+ // A.2.2. Special characters cont'd
+ { @"&permil;", 8240 },
+
+ // A.2.3. Symbols cont'd
+ { @"&prime;", 8242 },
+ { @"&Prime;", 8243 },
+
+ // A.2.2. Special characters cont'd
+ { @"&lsaquo;", 8249 },
+ { @"&rsaquo;", 8250 },
+
+ // A.2.3. Symbols cont'd
+ { @"&oline;", 8254 },
+ { @"&frasl;", 8260 },
+
+ // A.2.2. Special characters cont'd
+ { @"&euro;", 8364 },
+
+ // A.2.3. Symbols cont'd
+ { @"&image;", 8465 },
+ { @"&weierp;", 8472 },
+ { @"&real;", 8476 },
+ { @"&trade;", 8482 },
+ { @"&alefsym;", 8501 },
+ { @"&larr;", 8592 },
+ { @"&uarr;", 8593 },
+ { @"&rarr;", 8594 },
+ { @"&darr;", 8595 },
+ { @"&harr;", 8596 },
+ { @"&crarr;", 8629 },
+ { @"&lArr;", 8656 },
+ { @"&uArr;", 8657 },
+ { @"&rArr;", 8658 },
+ { @"&dArr;", 8659 },
+ { @"&hArr;", 8660 },
+ { @"&forall;", 8704 },
+ { @"&part;", 8706 },
+ { @"&exist;", 8707 },
+ { @"&empty;", 8709 },
+ { @"&nabla;", 8711 },
+ { @"&isin;", 8712 },
+ { @"&notin;", 8713 },
+ { @"&ni;", 8715 },
+ { @"&prod;", 8719 },
+ { @"&sum;", 8721 },
+ { @"&minus;", 8722 },
+ { @"&lowast;", 8727 },
+ { @"&radic;", 8730 },
+ { @"&prop;", 8733 },
+ { @"&infin;", 8734 },
+ { @"&ang;", 8736 },
+ { @"&and;", 8743 },
+ { @"&or;", 8744 },
+ { @"&cap;", 8745 },
+ { @"&cup;", 8746 },
+ { @"&int;", 8747 },
+ { @"&there4;", 8756 },
+ { @"&sim;", 8764 },
+ { @"&cong;", 8773 },
+ { @"&asymp;", 8776 },
+ { @"&ne;", 8800 },
+ { @"&equiv;", 8801 },
+ { @"&le;", 8804 },
+ { @"&ge;", 8805 },
+ { @"&sub;", 8834 },
+ { @"&sup;", 8835 },
+ { @"&nsub;", 8836 },
+ { @"&sube;", 8838 },
+ { @"&supe;", 8839 },
+ { @"&oplus;", 8853 },
+ { @"&otimes;", 8855 },
+ { @"&perp;", 8869 },
+ { @"&sdot;", 8901 },
+ { @"&lceil;", 8968 },
+ { @"&rceil;", 8969 },
+ { @"&lfloor;", 8970 },
+ { @"&rfloor;", 8971 },
+ { @"&lang;", 9001 },
+ { @"&rang;", 9002 },
+ { @"&loz;", 9674 },
+ { @"&spades;", 9824 },
+ { @"&clubs;", 9827 },
+ { @"&hearts;", 9829 },
+ { @"&diams;", 9830 }
+};
+
+// Taken from http://www.w3.org/TR/xhtml1/dtds.html#a_dtd_Special_characters
+// This is table A.2.2 Special Characters
+static HTMLEscapeMap gUnicodeHTMLEscapeMap[] = {
+ // C0 Controls and Basic Latin
+ { @"&quot;", 34 },
+ { @"&amp;", 38 },
+ { @"&apos;", 39 },
+ { @"&lt;", 60 },
+ { @"&gt;", 62 },
+
+ // Latin Extended-A
+ { @"&OElig;", 338 },
+ { @"&oelig;", 339 },
+ { @"&Scaron;", 352 },
+ { @"&scaron;", 353 },
+ { @"&Yuml;", 376 },
+
+ // Spacing Modifier Letters
+ { @"&circ;", 710 },
+ { @"&tilde;", 732 },
+
+ // General Punctuation
+ { @"&ensp;", 8194 },
+ { @"&emsp;", 8195 },
+ { @"&thinsp;", 8201 },
+ { @"&zwnj;", 8204 },
+ { @"&zwj;", 8205 },
+ { @"&lrm;", 8206 },
+ { @"&rlm;", 8207 },
+ { @"&ndash;", 8211 },
+ { @"&mdash;", 8212 },
+ { @"&lsquo;", 8216 },
+ { @"&rsquo;", 8217 },
+ { @"&sbquo;", 8218 },
+ { @"&ldquo;", 8220 },
+ { @"&rdquo;", 8221 },
+ { @"&bdquo;", 8222 },
+ { @"&dagger;", 8224 },
+ { @"&Dagger;", 8225 },
+ { @"&permil;", 8240 },
+ { @"&lsaquo;", 8249 },
+ { @"&rsaquo;", 8250 },
+ { @"&euro;", 8364 },
+};
+
+
+// Utility function for Bsearching table above
+static int EscapeMapCompare(const void *ucharVoid, const void *mapVoid) {
+ const unichar *uchar = (const unichar*)ucharVoid;
+ const HTMLEscapeMap *map = (const HTMLEscapeMap*)mapVoid;
+ int val;
+ if (*uchar > map->uchar) {
+ val = 1;
+ } else if (*uchar < map->uchar) {
+ val = -1;
+ } else {
+ val = 0;
+ }
+ return val;
+}
+
+@implementation NSString (GTMNSStringHTMLAdditions)
+
+- (NSString *)gtm_stringByEscapingHTMLUsingTable:(HTMLEscapeMap*)table
+ ofSize:(NSUInteger)size
+ escapingUnicode:(BOOL)escapeUnicode {
+ NSUInteger length = [self length];
+ if (!length) {
+ return self;
+ }
+
+ NSMutableString *finalString = [NSMutableString string];
+ NSMutableData *data2 = [NSMutableData dataWithCapacity:sizeof(unichar) * length];
+
+ // this block is common between GTMNSString+HTML and GTMNSString+XML but
+ // it's so short that it isn't really worth trying to share.
+ const unichar *buffer = CFStringGetCharactersPtr((CFStringRef)self);
+ if (!buffer) {
+ // We want this buffer to be autoreleased.
+ NSMutableData *data = [NSMutableData dataWithLength:length * sizeof(UniChar)];
+ if (!data) {
+ // COV_NF_START - Memory fail case
+ _GTMDevLog(@"couldn't alloc buffer");
+ return nil;
+ // COV_NF_END
+ }
+ [self getCharacters:[data mutableBytes]];
+ buffer = [data bytes];
+ }
+
+ if (!buffer || !data2) {
+ // COV_NF_START
+ _GTMDevLog(@"Unable to allocate buffer or data2");
+ return nil;
+ // COV_NF_END
+ }
+
+ unichar *buffer2 = (unichar *)[data2 mutableBytes];
+
+ NSUInteger buffer2Length = 0;
+
+ for (NSUInteger i = 0; i < length; ++i) {
+ HTMLEscapeMap *val = bsearch(&buffer[i], table,
+ size / sizeof(HTMLEscapeMap),
+ sizeof(HTMLEscapeMap), EscapeMapCompare);
+ if (val || (escapeUnicode && buffer[i] > 127)) {
+ if (buffer2Length) {
+ CFStringAppendCharacters((CFMutableStringRef)finalString,
+ buffer2,
+ buffer2Length);
+ buffer2Length = 0;
+ }
+ if (val) {
+ [finalString appendString:val->escapeSequence];
+ }
+ else {
+ _GTMDevAssert(escapeUnicode && buffer[i] > 127, @"Illegal Character");
+ [finalString appendFormat:@"&#%d;", buffer[i]];
+ }
+ } else {
+ buffer2[buffer2Length] = buffer[i];
+ buffer2Length += 1;
+ }
+ }
+ if (buffer2Length) {
+ CFStringAppendCharacters((CFMutableStringRef)finalString,
+ buffer2,
+ buffer2Length);
+ }
+ return finalString;
+}
+
+- (NSString *)gtm_stringByEscapingForHTML {
+ return [self gtm_stringByEscapingHTMLUsingTable:gUnicodeHTMLEscapeMap
+ ofSize:sizeof(gUnicodeHTMLEscapeMap)
+ escapingUnicode:NO];
+} // gtm_stringByEscapingHTML
+
+- (NSString *)gtm_stringByEscapingForAsciiHTML {
+ return [self gtm_stringByEscapingHTMLUsingTable:gAsciiHTMLEscapeMap
+ ofSize:sizeof(gAsciiHTMLEscapeMap)
+ escapingUnicode:YES];
+} // gtm_stringByEscapingAsciiHTML
+
+- (NSString *)gtm_stringByUnescapingFromHTML {
+ NSRange range = NSMakeRange(0, [self length]);
+ NSRange subrange = [self rangeOfString:@"&" options:NSBackwardsSearch range:range];
+
+ // if no ampersands, we've got a quick way out
+ if (subrange.length == 0) return self;
+ NSMutableString *finalString = [NSMutableString stringWithString:self];
+ do {
+ NSRange semiColonRange = NSMakeRange(subrange.location, NSMaxRange(range) - subrange.location);
+ semiColonRange = [self rangeOfString:@";" options:0 range:semiColonRange];
+ range = NSMakeRange(0, subrange.location);
+ // if we don't find a semicolon in the range, we don't have a sequence
+ if (semiColonRange.location == NSNotFound) {
+ continue;
+ }
+ NSRange escapeRange = NSMakeRange(subrange.location, semiColonRange.location - subrange.location + 1);
+ NSString *escapeString = [self substringWithRange:escapeRange];
+ NSUInteger length = [escapeString length];
+ // a squence must be longer than 3 (&lt;) and less than 11 (&thetasym;)
+ if (length > 3 && length < 11) {
+ if ([escapeString characterAtIndex:1] == '#') {
+ unichar char2 = [escapeString characterAtIndex:2];
+ if (char2 == 'x' || char2 == 'X') {
+ // Hex escape squences &#xa3;
+ NSString *hexSequence = [escapeString substringWithRange:NSMakeRange(3, length - 4)];
+ NSScanner *scanner = [NSScanner scannerWithString:hexSequence];
+ unsigned value;
+ if ([scanner scanHexInt:&value] &&
+ value < USHRT_MAX &&
+ value > 0
+ && [scanner scanLocation] == length - 4) {
+ unichar uchar = value;
+ NSString *charString = [NSString stringWithCharacters:&uchar length:1];
+ [finalString replaceCharactersInRange:escapeRange withString:charString];
+ }
+
+ } else {
+ // Decimal Sequences &#123;
+ NSString *numberSequence = [escapeString substringWithRange:NSMakeRange(2, length - 3)];
+ NSScanner *scanner = [NSScanner scannerWithString:numberSequence];
+ int value;
+ if ([scanner scanInt:&value] &&
+ value < USHRT_MAX &&
+ value > 0
+ && [scanner scanLocation] == length - 3) {
+ unichar uchar = value;
+ NSString *charString = [NSString stringWithCharacters:&uchar length:1];
+ [finalString replaceCharactersInRange:escapeRange withString:charString];
+ }
+ }
+ } else {
+ // "standard" sequences
+ for (unsigned i = 0; i < sizeof(gAsciiHTMLEscapeMap) / sizeof(HTMLEscapeMap); ++i) {
+ if ([escapeString isEqualToString:gAsciiHTMLEscapeMap[i].escapeSequence]) {
+ [finalString replaceCharactersInRange:escapeRange withString:[NSString stringWithCharacters:&gAsciiHTMLEscapeMap[i].uchar length:1]];
+ break;
+ }
+ }
+ }
+ }
+ } while ((subrange = [self rangeOfString:@"&" options:NSBackwardsSearch range:range]).length != 0);
+ return finalString;
+} // gtm_stringByUnescapingHTML
+
+
+
+@end
View
66 Externals/TBXML/NSDataAdditions.h
@@ -0,0 +1,66 @@
+
+#import <Foundation/Foundation.h>
+
+@interface NSData (NSDataAdditions)
+
+// ================================================================================================
+// Created by Tom Bradley on 21/10/2009.
+// Version 1.3
+//
+// Copyright (c) 2009 Tom Bradley
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+// ================================================================================================
+
++ (NSData *) dataWithUncompressedContentsOfFile:(NSString *)aFile;
+
+
+
+// ================================================================================================
+// base64.h
+// ViewTransitions
+//
+// Created by Neo on 5/11/08.
+// Copyright 2008 Kaliware, LLC. All rights reserved.
+//
+// FOUND HERE http://idevkit.com/forums/tutorials-code-samples-sdk/8-nsdata-base64-extension.html
+// ================================================================================================
++ (NSData *) dataWithBase64EncodedString:(NSString *) string;
+- (id) initWithBase64EncodedString:(NSString *) string;
+
+- (NSString *) base64Encoding;
+- (NSString *) base64EncodingWithLineLength:(unsigned int) lineLength;
+
+
+
+// ================================================================================================
+// NSData+gzip.h